首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多線程調度四大方案:join、wait/notify、CountDownLatch、CyclicBarrier 實戰對比

     編輯:Java 相關知識

前言

多線程協作中,如何控制執行順序?本文對比四種調度方案:**Thread.join()、Object.wait/notify、CountDownLatch、CyclicBarrier**,分析適用場景、優缺點與代碼範例,並給出生產級選型建議。

方案一:Thread.join() —— 等待線程終止

Object lock = new Object();
boolean ready = false;

// 生產者
synchronized (lock) { prepare(); ready = true; lock.notify(); }

// 消費者
synchronized (lock) { while (!ready) lock.wait(); consume(); }
  • ✅ 靈活:可實現任意狀態機協作 (生產消費、讀寫鎖、屏障)。
  • ❌ 易錯:需正確處理鎖、while 迴圈、虛假喚醒、notify vs notifyAll、死鎖風險。
  • 適用:底層框架開發、特殊協作邏輯 (如交替打印、順序執行)。

方案三:CountDownLatch —— 一次性倒計時門閂

class DecryptService {
    private final Map holders = new ConcurrentHashMap<>();

    public String decryptAsync(Long fid, File encFile) {
        CountDownLatch latch = new CountDownLatch(1);
        holders.put(fid, new DecryptHolder(latch));
        executor.submit(() -> {
            try { String path = decrypt(encFile); holder.setPath(path); }
            finally { latch.countDown(); }
        });
        return latch; // 返回 latch 供調用者 await
    }

    public String getDecryptedPath(Long fid) throws InterruptedException {
        DecryptHolder h = holders.get(fid);
        h.latch.await(); // 等待解密完成
        return h.path;
    }
    static class DecryptHolder { CountDownLatch latch; String path; ... }
}

方案四:CyclicBarrier —— 可重複使用的攔截器

 { prepare(); barrier.await(); race(); }).start();
}
  • ✅ 可重用:reset() 重置計數 (會觸發 BrokenBarrierException)。
  • ✅ 支援 **屏障動作** (Runnable) 在最後一個線程到達時執行 (合併結果、觸發下階段)。
  • ❌ 異常處理:任一線程 await() 拋異常/中斷,其他線程收到 BrokenBarrierException。
  • 適用:多線程分階段計算 (MapReduce 風格)、並行測試壓力點、遊戲匹配等待。

核心對比表

特性join()wait/notifyCountDownLatchCyclicBarrier
等待對象Thread 終止任意條件 (狀態)計數器歸零所有參與者到達
可重用否 (線程不可重啟)是否是 (reset())
同步模式一對一靈活多對一 (聚合)多對多 (齊聚)
攔截動作無手工實現無支援 (Runnable)
異常傳播InterruptedExceptionInterruptedExceptionInterruptedExceptionInterruptedException + BrokenBarrierException
典型場景主線程等初始化生產消費、狀態機並行任務聚合、啟動等待分階段並行計算、賽馬場景

進階:Phaser (JDK 7+) —— 更靈活的分階段同步器

  • 支援動態註冊/註銷參與者 (register(), arriveAndDeregister())。
  • 階段數無上限 (getPhase()),可跨代換任務。
  • 適用:動態並行任務流水線、遞歸分治同步。

實務選型指南

  1. 等待單一線程結束 → join() (或 Future.get() 配合線程池)。
  2. 啟動 N 個獨立任務,主線程聚合結果 → CountDownLatch (或 CompletableFuture.allOf())。
  3. N 個線程分階段同步推進 → CyclicBarrier / Phaser。
  4. 生產消費 / 狀態機協作 → BlockingQueue / wait/notify (底層) / Lock + Condition。
  5. 高層抽象優先:CompletableFuture, parallelStream, ExecutorService.invokeAll。

總結

線程調度工具從低層 join/wait/notify 進化到高層 CountDownLatch/CyclicBarrier/Phaser/CompletableFuture。**核心原則**:用最高層級能滿足需求的 API,避免手工管理鎖與狀態。理解各工具的語義邊界 (一次性 vs 可重用、聚合 vs 齊聚) 是正確選型的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved