CountDownLatch 類是一個倒計時計數器,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。用給定的計數初始化 CountDownLatch。由於調用了countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之后,會釋放所有等待的線程,await 的所有后續調用都將立即返回。
CountDownLatch 是一個通用同步工具,它有很多用途。將計數1初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,或入口:在通過調用 countDown() 的線程打開入口前,所有調用 await 的線程都一直在入口處等待。用N初始化的 CountDownLatch 可以使一個線程在N個線程完成某項操作之前一直等待,或者使其在某項操作完成N次之前一直等待。
CountDownLatch猶如比賽的發令官,多條線程猶如運動員。倒計時到零時一聲槍響,運動員開始比賽,即多條線程開始運行。
使用CountDownLatch很簡單,因為它只提供了一個構造器:
CountDownLatch(int count):構造一個用給定計數初始化的CountDownLatch。
在線程中調用CountDownLatch對象的await()方法,會使當前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷。而調用countDown()方法會遞減鎖存器的計數,如果計數到達零,則釋放所有等待的線程。
見下面程序:啟動三個線程等待主線程發布命令,主線程發布命令后等待三個線程運行完后的反饋。
- public class CountDownLatchDemo {
- public static void main(String[] args) {
- //線程池
- ExecutorService pool = Executors.newCachedThreadPool();
- //定義兩個倒計時計數器
- //等待命令倒計時計數器
- final CountDownLatch countOrder = new CountDownLatch(1);
- //等待反饋倒計時計數器
- final CountDownLatch countAnswer = new CountDownLatch(3);
- //3個子線程
- for(int i = 0; i < 3; i++){
- Runnable target = new Runnable() {
- @Override
- public void run() {
- try {
- System.out.println(Thread.currentThread().getName() +
- "-等待命令");
- //等待countOrder為0時停止等待,向下執行
- countOrder.await();
- System.out.println(Thread.currentThread().getName() +
- "-得到命令,開始執行");
- Thread.sleep((long)(Math.random()*10000));
- System.out.println(Thread.currentThread().getName() +
- "-命令執行完成,回應結果");
- //將countAnswer減一
- countAnswer.countDown();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- };
- pool.execute(target);
- }
- //主線程
- try{
- Thread.sleep((long)(Math.random()*10000));
- System.out.println(Thread.currentThread().getName() +
- "-即將發布命令");
- //將countOrder減一
- countOrder.countDown();
- System.out.println(Thread.currentThread().getName() +
- "-已發布命令,等待回應");
- //等待回應
- countAnswer.await();
- System.out.println(Thread.currentThread().getName() +
- "-已收到所有回應結果");
- }catch(InterruptedException e) {
- e.printStackTrace();
- }
- pool.shutdown();
- }
- }
運行程序

看到3個子線程在接到主線程命令前都等待,當主線程調用了countDown() 方法后減為零,3個子線程開始運行,並且主線程等待子線程運行完后的回應。3個子線程沒運行完一個調用countDown() 方法,當3個都運行完后,主線程收到回應。