整理來源:http://www.javashuo.com/article/p-xkdlaiet-cc.htmlhtml
可重入: 單線程能夠重複進入,但要重複退出
可中斷: lock.lockInterruptibly()
可限時: 超時不能得到鎖,就返回false,不會永久等待構成死鎖
公平鎖: 先來先得, public ReentrantLock(boolean fair), 默認鎖不公平的, 根據線程優先級競爭
reentrantlock須要手工釋放鎖經過調用(unlock()方法),默認爲非公平鎖,new ReentrantLock(true)設置爲公平鎖能夠防止飢餓現象
數組
public interface Lock { // 獲取鎖,若當前lock被其餘線程獲取;則此線程阻塞等待lock被釋放 // 若是採用Lock,必須主動去釋放鎖,而且在發生異常時,不會自動釋放鎖 void lock(); // 獲取鎖,若當前鎖不可用(被其餘線程獲取); // 則阻塞線程,等待獲取鎖,則這個線程可以響應中斷,即中斷線程的等待狀態 void lockInterruptibly() throws InterruptedException; // 來嘗試獲取鎖,若是獲取成功,則返回true; // 若是獲取失敗(即鎖已被其餘線程獲取),則返回false // 也就是說,這個方法不管如何都會當即返回 boolean tryLock(); // 在拿不到鎖時會等待必定的時間 // 等待過程當中,能夠被中斷 // 超過期間,依然獲取不到,則返回false;不然返回true boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 釋放鎖 void unlock(); // 返回一個綁定該lock的Condtion對象 // 在Condition#await()以前,鎖會被該線程持有 // Condition#await() 會自動釋放鎖,在wait返回以後,會自動獲取鎖 Condition newCondition(); }
condition: 多線程
public interface Condition { void await() throws InterruptedException; void awaitUninterruptibly(); long awaitNanos(long nanosTimeout) throws InterruptedException; boolean await(long time, TimeUnit unit) throws InterruptedException; boolean awaitUntil(Date deadline) throws InterruptedException; void signal(); void signalAll(); }
說明
await()方法會使當前線程等待,同時釋放當前鎖,當其餘線程中使用signal()時或者signalAll()方法時,線程會從新得到鎖並繼續執行。或者當線程被中斷時,也能跳出等待。這和Object.wait()方法很類似。
awaitUninterruptibly()方法與await()方法基本相同,但awaitUninterruptibly()方法不會在等待過程當中響應中斷。
singal()方法用於喚醒一個在等待中的線程。相對的singalAll()方法會喚醒全部在等待中的線程。這和Obejct.notify()方法相似。
condition.await()方法必須在lock.lock()與lock.unlock()方法之間調用併發
CountDownLatch(int count) //實例化一個倒計數器,count指定計數個數 countDown() // 計數減一 await() //等待,當計數減到0時,全部線程並行執行 public class CountDownLatchDemo implements Runnable{ static final CountDownLatch latch = new CountDownLatch(10); static final CountDownLatchDemo demo = new CountDownLatchDemo(); @Override public void run() { // 模擬檢查任務 try { Thread.sleep(new Random().nextInt(10) * 1000); System.out.println("check complete"); } catch (InterruptedException e) { e.printStackTrace(); } finally { //計數減一 //放在finally避免任務執行過程出現異常,致使countDown()不能被執行 latch.countDown(); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(10); for (int i=0; i<10; i++){ exec.submit(demo); } // 等待檢查 latch.await(); // 發射火箭 System.out.println("Fire!"); // 關閉線程池 exec.shutdown(); } }
static class TaskThread extends Thread { CyclicBarrier barrier; public TaskThread(CyclicBarrier barrier) { this.barrier = barrier; } @Override public void run() { try { Thread.sleep(1000); System.out.println(getName() + " 到達柵欄 A"); barrier.await(); System.out.println(getName() + " 衝破柵欄 A"); Thread.sleep(2000); System.out.println(getName() + " 到達柵欄 B"); barrier.await(); System.out.println(getName() + " 衝破柵欄 B"); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { int threadNum =5; CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + " 完成最後任務"); } }); for(int i = 0; i < threadNum; i++) { new TaskThread(barrier).start(); } } }
LockSupport:一個線程阻塞工具, 能夠在任意位置讓線程阻塞.
dom
LockSupport.park(); LockSupport.unpark(t1);
優勢:LockSupport不須要在同步代碼塊裏 。因此線程間也不須要維護一個共享的同步對象了,實現了線程間的解耦
unpark函數能夠先於park調用,因此不須要擔憂線程間的執行的前後順序ide
併發容器函數
synchronizedMap
ConcurrentHashMap
BlockingQueue:阻塞隊列, 主要用於多線程之間共享數據.當一個線程讀取數據時, 若是隊列是空的, 則當前線程會進入等待狀態.若是隊列滿了, 當一個線程嘗試寫入數據時, 一樣會進入等待狀態.
CopyOnWriteArrayList:經過在新增元素時, 複製一份新的數組出來, 並在其中寫入數據, 以後將原數組引用指向到新數組.其Add操做是在內部經過ReentrantLock進行鎖保護, 防止多線程場景複製多份數組.而Read操做內部無鎖, 直接返回數組引用, 併發下效率高, 所以適用於讀多寫少的場景工具