CountDownLatch(倒數閂鎖)是一種同步輔助類,允許一個或多個線程等待其他線程完成操作。它就像一扇門:在計數器歸零前門保持關閉,所有等待線程阻塞;計數器歸零時門打開,所有等待線程同時被釋放繼續執行。
CountDownLatch(int count):建構子,初始化計數器void countDown():計數器減 1,表示一個任務完成void await():阻塞當前線程,直到計數器歸零boolean await(long timeout, TimeUnit unit):帶超時的等待long getCount():獲取當前計數值10 位運動員等待裁判發令同時起跑,當最後一名到達終點時比賽結束。這需要兩個閉鎖協調:
import java.util.concurrent.CountDownLatch;
class Runner implements Runnable {
private final int id;
private final CountDownLatch startSignal;
private final CountDownLatch finishSignal;
public Runner(int id, CountDownLatch startSignal, CountDownLatch finishSignal) {
this.id = id;
this.startSignal = startSignal;
this.finishSignal = finishSignal;
}
@Override
public void run() {
try {
System.out.println(id + " 號選手準備就緒");
startSignal.await(); // 等待發令
// 模擬跑步時間
Thread.sleep((long) (Math.random() * 3000));
System.out.println(id + " 號選手到達終點");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
finishSignal.countDown(); // 到達終點,計數器減一
}
}
}
public class RaceSimulation {
public static void main(String[] args) throws InterruptedException {
int runnerCount = 10;
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch finishSignal = new CountDownLatch(runnerCount);
// 啟動所有選手線程
for (int i = 1; i <= runnerCount; i++) {
new Thread(new Runner(i, startSignal, finishSignal)).start();
}
System.out.println("裁判準備發令...");
Thread.sleep(1000);
System.out.println("裁判:開始跑!");
startSignal.countDown(); // 發令
long startTime = System.nanoTime();
finishSignal.await(); // 等待所有選手到達
long endTime = System.nanoTime();
System.out.println("裁判:所有人到達終點!");
System.out.printf("比賽耗時:%.2f 秒%n", (endTime - startTime) / 1e9);
}
}
| 特性 | CountDownLatch | CyclicBarrier |
|---|---|---|
| 可重用性 | 一次性,計數歸零不可重置 | 可重用,攔截點可重置 |
| 等待對象 | 等待事件(countDown) | 等待其他線程(await) |
| 適用場景 | 一線程等多線程完成 | 多線程互相等待匯合 |
| 攔截動作 | 不支援 | 支援 barrierAction |