CountDownLatch
CountDownLatch這個類使一個線程等待其他線程完成各自的工作再執(zhí)行,例如主線程希望子線程完成操作后讓自線程使用。
CountDownLatch是通過計(jì)數(shù)器實(shí)現(xiàn),每次完成一個任務(wù)后,計(jì)數(shù)器減一當(dāng)為0時,CountDownLatch.await()方法的線程就可以恢復(fù)執(zhí)行任務(wù)。

如圖我們Tw1線程Tw2線程 執(zhí)行了await方法 進(jìn)行等待,這是countDownlotch設(shè)置為5,ta、tb、tc、td調(diào)用countDown方法讓計(jì)數(shù)器減一,當(dāng)計(jì)數(shù)器為0時,Tw1、Tw2線程恢復(fù)運(yùn)行。
注意:不是子countdownlatch不是線程的數(shù)量、而且當(dāng)countdownchlatch不等于線程數(shù)
public class UseCountDownLatch {
static CountDownLatch latch = new CountDownLatch(4);
private static class InitThread implements Runnable{
public void run() {
System.out.println("Thread_"+Thread.currentThread().getId()
+" ready init work......");
latch.countDown();
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new BusiThread()).start();
for(int i=0;i<=3;i++){
Thread thread = new Thread(new InitThread());
thread.start();
}
latch.await();
System.out.println("Main do ites work........");
}
}
demo中演示的是一段 開啟四個子線程,主線程調(diào)用await進(jìn)入阻塞狀態(tài),調(diào)用countDown方法,當(dāng)countdownchlatch為0時,主線程阻塞狀態(tài)恢復(fù)。
CyclicBarrier
CyclicBarrier是一種線程間的屏障,一組線程到達(dá)一個屏障(也可以叫同步點(diǎn))時被阻塞,直到最后一個線程到達(dá)屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續(xù)運(yùn)行。
CyclicBarrier默認(rèn)的構(gòu)造方法是CyclicBarrier(int parties),其參數(shù)表示屏障攔截的線程數(shù)量,每個線程調(diào)用await方法告訴CyclicBarrier我已經(jīng)到達(dá)了屏障,然后當(dāng)前線程被阻塞。
CyclicBarrier還提供一個更高級的構(gòu)造函數(shù)CyclicBarrier(int parties,Runnable barrierAction),用于在線程到達(dá)屏障時,優(yōu)先執(zhí)行barrierAction,方便處理更復(fù)雜的業(yè)務(wù)場景。

public class UseCyclicBarrier {
private static CyclicBarrier barrier
= new CyclicBarrier(4,new CollectThread());
public static void main(String[] args) {
for(int i=0;i<4;i++){
Thread thread = new Thread(new SubThread());
thread.start();
}
}
/*匯總的任務(wù)*/
private static class CollectThread implements Runnable{
@Override
public void run() {
System.out.println("do other business........");
}
}
/*相互等待的子線程*/
private static class SubThread implements Runnable{
@Override
public void run() {
long id = Thread.currentThread().getId();
resultMap.put(Thread.currentThread().getId()+"",id);
try {
Thread.sleep(1000+id);
System.out.println("Thread_"+id+" ....do something ");
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
這里我們開啟了4個子線程,他們?nèi)客瓿晒ぷ骱?,匯總線程CollectThread執(zhí)行。
兩者區(qū)別
CountDownLatch的計(jì)數(shù)器只能使用一次,而CyclicBarrier的計(jì)數(shù)器可以反復(fù)使用。
CountDownLatch.await一般阻塞工作線程,所有的進(jìn)行預(yù)備工作的線程執(zhí)行countDown,而CyclicBarrier通過工作線程調(diào)用await從而自行阻塞,直到所有工作線程達(dá)到指定屏障,再大家一起往下走。
在控制多個線程同時運(yùn)行上,CountDownLatch可以不限線程數(shù)量,而CyclicBarrier是固定線程數(shù)。
同時,CyclicBarrier還可以提供一個barrierAction,合并多線程計(jì)算結(jié)果。