java.util.concurrent.CountDownLatch 是一個同步輔助類,允許一個或多個線程等待其他線程完成操作。它內部維護一個計數器,透過 countDown() 遞減,await() 阻塞直到計數歸零。
CyclicBarriercountDown 的線程等待,只阻塞 await 的線程裁判等選手就位 → 發令 → 選手跑完全程 → 裁判收集成績
public class CountdownLatchTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
// 裁判發令鎖 (計數 1)
final CountDownLatch cdOrder = new CountDownLatch(1);
// 選手完成鎖 (計數 3)
final CountDownLatch cdAnswer = new CountDownLatch(3);
// 3 位選手
for (int i = 0; i < 3; i++) {
service.execute(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 準備就緒");
cdOrder.await(); // 等待發令
System.out.println(Thread.currentThread().getName() + " 起跑");
Thread.sleep((long)(Math.random() * 10000)); // 模擬跑步
System.out.println(Thread.currentThread().getName() + " 到達終點");
cdAnswer.countDown(); // 完成計數 -1
} catch (Exception e) { e.printStackTrace(); }
});
}
// 裁判線程
try {
Thread.sleep((long)(Math.random() * 10000));
System.out.println("裁判:發令!");
cdOrder.countDown(); // 開閘
System.out.println("裁判:等待選手到達...");
cdAnswer.await(); // 阻塞直到計數歸零
System.out.println("裁判:所有選手到達,比賽結束");
} catch (Exception e) { e.printStackTrace(); }
service.shutdown();
}
}
pool-1-thread-1 準備就緒
pool-1-thread-2 準備就緒
pool-1-thread-3 準備就緒
裁判:發令!
pool-1-thread-2 起跑
pool-1-thread-1 起跑
pool-1-thread-3 起跑
pool-1-thread-3 到達終點
pool-1-thread-1 到達終點
pool-1-thread-2 到達終點
裁判:所有選手到達,比賽結束
| 場景 | 做法 |
|---|---|
| 並行初始化多個服務 | 主線程 await,各服務啟動後 countDown |
| 分階段任務同步 | 每階段建立新 CountDownLatch |
| 需重複使用 | 改用 CyclicBarrier 或 Phaser |
| 超時控制 | 使用 await(timeout, unit) 避免無限阻塞 |