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

Java 併發工具類 CountDownLatch 深度解析:原理、模式與實戰示例

     編輯:Java 綜合教學

核心定位

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

關鍵點解讀

  • Driver(監工):先做準備,countDown() 釋放工人;隨後 await() 等待收工;
  • Worker(工人):await() 等待開工令,doWork() 幹活,countDown() 報工;
  • 兩把閂職責正交:startSignal 控制並發起跑,doneSignal 控制併發收攏。

進階用法與注意事項

  • 不可重用:計數器歸零後無法重置,需新建實例;循環場景請用 CyclicBarrier;
  • 異常處理:await() 可響應中斷,拋出 InterruptedException,業務代碼需妥善處理;
  • 超時等待:await(long timeout, TimeUnit unit) 避免無限阻塞;
  • 計數器初始值:必須在構造時指定,且只能遞減,不可增長。

對比:CountDownLatch vs CyclicBarrier vs Phaser

特性CountDownLatchCyclicBarrierPhaser
可重用否是是(分階段)
動態註冊否否是
適用場景一對多/多對一 等待多方會合複雜分階段同步

總結

CountDownLatch 以極簡 API 解決「一個/多個線程等待 N 個事件完成」的經典同步問題,雙閂模式更能優雅實現「統一起跑、統一收攏」的併發協調。掌握其不可重用特性與異常處理,是寫出健壯併發代碼的基石。

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