CountDownLatch(倒計時門閂)是 java.util.concurrent 包下的同步工具,本質是一個共享鎖/信號量。形象比喻:一扇有 N 個插銷的大門,調用 await() 的線程被擋在門外,直到其他線程調用 countDown() 將計數器減至 0,大門打開,所有等待線程繼續執行。
Oracle 官方文檔範例改良:
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
new Driver().run();
}
}
class Driver {
static final int N = 5;
public void run() throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1); // 單一啟動閂
CountDownLatch doneSignal = new CountDownLatch(N); // 完成閂,計數 N
for (int i = 0; i < N; i++) {
new Thread(new Worker(startSignal, doneSignal)).start();
}
doSomething(); // 主線程準備工作
startSignal.countDown(); // 開閂:通知所有 Worker 開始
doneSignal.await(); // 等待:阻塞直到所有 Worker 完成
doSomething(); // 後續處理
}
private void doSomething() { System.out.println("doSomething"); }
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
public Worker(CountDownLatch start, CountDownLatch done) {
this.startSignal = start; this.doneSignal = done;
}
@Override public void run() {
try {
startSignal.await(); // 等待啟動信號
doWork(); // 執行任務
doneSignal.countDown(); // 任務完成,計數 -1
} catch (InterruptedException e) { e.printStackTrace(); }
}
private void doWork() { System.out.println("worker work."); }
}
doSomething worker work. worker work. worker work. worker work. worker work. doSomething
countDown() 釋放工人;隨後 await() 等待收工;await() 等待開工令,doWork() 幹活,countDown() 報工;startSignal 控制並發起跑,doneSignal 控制併發收攏。CyclicBarrier;await() 可響應中斷,拋出 InterruptedException,業務代碼需妥善處理;await(long timeout, TimeUnit unit) 避免無限阻塞;| 特性 | CountDownLatch | CyclicBarrier | Phaser |
|---|---|---|---|
| 可重用 | 否 | 是 | 是(分階段) |
| 動態註冊 | 否 | 否 | 是 |
| 適用場景 | 一對多/多對一 等待 | 多方會合 | 複雜分階段同步 |
CountDownLatch 以極簡 API 解決「一個/多個線程等待 N 個事件完成」的經典同步問題,雙閂模式更能優雅實現「統一起跑、統一收攏」的併發協調。掌握其不可重用特性與異常處理,是寫出健壯併發代碼的基石。