本文的示例參見JavaDoc API
簡介
CountDownLatch是一個同步的輔助類,它可以允許一個或多個線程等待,直到一組在其它線程中的操作執(zhí)行完成。
一個CountDownLatch會通過一個給定的count數(shù)來被初始化。其中await()方法會一直阻塞,直到當(dāng)前的count被減到0,而這個過程是通過調(diào)用countDown()方法來實現(xiàn)的。在await()方法不再阻塞以后,所有等待的線程都會被釋放,并且任何await()的子調(diào)用都會立刻返回。這是一次性的--count不能被重置。如果你需要一種能重置count的版本,請考慮使用CyclicBarrier。
CountDownlatch是一個多功能的同步工具,可以被用于各種目的。一個CountDownLatch通過一個值為1的count被初始化,來作為一個開/關(guān)的門或門閂:所有調(diào)用了await()的線程都會在門前等待,直到門被一個線程通過調(diào)用countDown()打開。一個被初始化為N的CountDownLatch可以被用來“在N個線程都完成了某種操作(或者一些操作已經(jīng)被完成了N次)之后創(chuàng)建一個線程”。
CountDownLatch一個有用的屬性就是它不需要線程們在繼續(xù)執(zhí)行之前,調(diào)用countDown來等待count被減到0。它簡單地阻止了任何調(diào)用了await()的線程繼續(xù),直到所有的線程都能夠通過。
示例
下面請看一個應(yīng)用場景:
有1個driver和5個worker,需要滿足以下兩點要求:
- 當(dāng)driver完成了全部的工作之后才允許worker們開始工作;
- 當(dāng)所有的worker都完成了自己的工作之后,driver主線程才能結(jié)束。
public class Driver {
public static void main(String[] args) throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(5);
// 依次創(chuàng)建并啟動5個worker線程
for (int i = 0; i < 5; ++i) {
new Thread(new Worker(startSignal, doneSignal)).start();
}
System.out.println("Driver is doing something...");
System.out.println("Driver is Finished, start all workers ...");
startSignal.countDown(); // Driver執(zhí)行完畢,發(fā)出開始信號,使所有的worker線程開始執(zhí)行
doneSignal.await(); // 等待所有的worker線程執(zhí)行結(jié)束
System.out.println("Finished.");
}
}
class Worker implements Runnable{
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
public void run() {
try {
startSignal.await(); // 等待Driver線程執(zhí)行完畢,獲得開始信號
System.out.println("Working now ...");
doneSignal.countDown(); // 當(dāng)前worker執(zhí)行完畢,釋放一個完成信號
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
運行結(jié)果:
Driver is doing something...
Driver is Finished, start all workers ...
Working now ...
Working now ...
Working now ...
Working now ...
Working now ...
Finished.