如上圖所示,當7個線程都完成latch.countDown調用後,最下面那條線程會從latch.await返回,繼續執行後面的代碼html
咱們來看一個具體的例子。假設咱們使用一臺多核的機器對一組數據進行排序,那麼咱們能夠把這組數據分到不一樣線程中進行排序,而後合併;能夠利用線程池來管理多線程;能夠將CountDownLatch用做各個分組數據都排好序的通知。下面是代碼片斷:java
先看主線程編程
int count = 10; final CountDownLatch latch = new CountDownLatch(count); int[] datas = new int[10204]; int step = datas.length / count; for (int i=0; i < count; i++) { int start = i * step; int end = (i+1) * step; if (i == count - 1) end = datas.length; threadpool.execute(new MyRunnable(latch, datas, start, end)); } latch.await(); //合併數據
咱們再看一下具體任務的代碼,即MyRunnable的run方法的實現:多線程
public void run() { //數據排序 latch.countDown(); }
|
CountDownLatch
|
CyclicBarrier
|
適用場景
|
主線程等待其餘工做線程結束
|
多個線程相互等待,直到全部線程都達到一個障礙點Barrier
|
主要方法
|
CountDownLatch(int count) 主線程調用:初始化計數
await() 主線程調用 : 阻塞,直到等待計數爲0時解除阻塞
countDown() 工做線程調用 : 計數減1
|
CyclicBarrier(int parties , Runnnable barrierAction) : 初始化參與者數量和障礙點執行Action,action可選,由主線程初始化
await() : 由工做線程調用,每被調用一次,計數便會減小1,並阻塞住當前線程 , 直到全部線程都達到障礙點
|
等待結束
|
各線程之間再也不相互影響, 能夠繼續作本身的事情, 再也不執行下一個工做目標。
|
在障礙點到達後, 容許全部線程繼續執行,到達下一個目標後,能夠恢復使用CyclicBarrier, barrier 在釋放等待線程後能夠重用
|
異常
|
|
若是其中一個線程因爲中斷、錯誤、或者超時致使永久離開障礙點,其餘線程也將拋出異常。
|
int count = 10; final CyclicBarrier barrier = new CyclicBarrier(count + 1); int[] datas = new int[10204]; int step = datas.length / count; for (int i=0; i < count; i++) { int start = i * step; int end = (i+1) * step; if (i == count - 1) end = datas.length; threadpool.execute(new MyRunnable(barrier, datas, start, end)); } barrier.await(); //合併數據
能夠看到CyclicBarrier對象傳入的參數值比CountDownLatch大1,緣由是構造CountDownLatch的參數是調用countDown的數量,而CyclicBarrier的數量是await的數量併發
public void run() { //數據排序 try { barrier.await(); }catch (...) }
public Semaphore(int permits) { //參數permits表示許可數目,即同時能夠容許多少線程進行訪問
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) { //這個多了一個參數fair表示是不是公平的,即等待時間越久的越先獲取許可
sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
}
semaphore.acquire(); try { //調用遠程通訊的方法 } finally { semaphore.release(); }