封裝狀態,協調線程控制流:決定線程「等待」還是「繼續」。
| 工具 | 核心隱喻 | 典型場景 | 關鍵方法 |
|---|---|---|---|
| CountDownLatch | 倒計時閂鎖 | 主線程等待多個初始化任務完成 | countDown(), await() |
| CyclicBarrier | 循環柵欄 | 多線程分階段計算,階段間同步 | await() |
| Semaphore | 信號量/許可證 | 資源池限流 (連接池、線程池) | acquire(), release() |
| BlockingQueue | 阻塞隊列 | 生產者-消費者、任務緩衝 | put(), take() |
// 主線程等待 10 個子任務完成
CountDownLatch latch = new CountDownLatch(10);
ExecutorService es = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
es.execute(() -> {
doWork(); // 耗時操作
latch.countDown(); // 計數 -1
});
}
latch.await(); // 阻塞直到計數歸零
System.out.println("All tasks done");
// 輸出順序:所有子任務 running → 依次 finished → 主線程 continue
特點:計數器只能遞減一次,不可重置。FutureTask 也可作為閉鎖 (get() 等待完成)。
// 模擬 3 個數據庫連接,10 個線程競爭
Semaphore sem = new Semaphore(3); // 3 個許可證
for (int i = 0; i < 10; i++) new Thread(() -> {
sem.acquire(); // 獲取許可,無則阻塞
useConnection(); // 業務邏輯
sem.release(); // 歸還許可
}).start();
// 輸出:同時只有 3 個線程在 useConnection,其餘阻塞等待
公平性:構造函數 new Semaphore(permits, true) 開啟公平模式 (FIFO),性能稍低。
// 5 線程分階段任務,每階段需全部到達才能進入下一階段
CyclicBarrier barrier = new CyclicBarrier(5, () ->
System.out.println("所有線程到達柵欄,執行匯總邏輯..."));
for (int i = 0; i < 5; i++) new Thread(() -> {
phase1();
barrier.await(); // 阻塞等待
phase2();
barrier.await();
phase3();
}).start();
// 輸出:各線程 phase1 不同步 → 到達 await 阻塞 → 最後一個到達觸發 barrierAction → 所有線程同時繼續 phase2
區別:Latch 計數歸零一次性;Barrier 到達方數可循環重用,且可選「柵欄動作」。
// 有界隊列,生產者慢消費者快 → 消費者阻塞;生產者快消費者慢 → 生產者阻塞
BlockingQueue queue = new LinkedBlockingQueue<>(100);
// 生產者
new Thread(() -> {
while (true) {
String item = produce();
queue.put(item); // 滿則阻塞
}
}).start();
// 6 個消費者
for (int i = 0; i < 6; i++) new Thread(() -> {
while (true) {
String item = queue.take(); // 空則阻塞
consume(item);
}
}).start();
// 輸出:每秒生產 1 個,6 消費者輪流消費,天然負載均衡
AbstractQueuedSynchronizer (AQS) 實現,理解 AQS 狀態變更與節點排隊機制,可洞悉底層原理。Phaser (Java 7+) 結合了 Latch 和 Barrier 功能,支持動態註冊/註銷參與者,更靈活。CompletableFuture 提供了更高級的組合式異步編排能力 (thenCompose, allOf, anyOf),現代並發首選。