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

Java 並發編程:CyclicBarrier 循環柵欄實戰詳解與對比

     編輯:Java 相關知識

CyclicBarrier 核心概念

CyclicBarrier(循環柵欄)讓一組線程互相等待,直到所有線程都到達屏障點,然後同時繼續執行。與 CountDownLatch 不同,它強調「多線程互相等待,缺一不可」,且可重用。

核心 API

  • CyclicBarrier(int parties):建構子,指定攔截線程數
  • CyclicBarrier(int parties, Runnable barrierAction):攔截動作版本,所有線程到達後先執行 barrierAction
  • int await():到達屏障點等待,返回到達序號(0 為最後到達)
  • int await(long timeout, TimeUnit unit):帶超時等待
  • void reset():重置柵欄,可重用
  • boolean isBroken():檢查是否處於損壞狀態

經典場景:春遊集合出發

10 人春遊,約定所有人到達集合點才能一起出發。每個人到達時間不同,必須等待最後一人。

完整代碼實作

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

class Tourist implements Runnable {
    private final int id;
    private final CyclicBarrier barrier;

    public Tourist(int id, CyclicBarrier barrier) {
        this.id = id;
        this.barrier = barrier;
    }

    @Override
    public void run() {
        try {
            // 模擬不同到達時間
            Thread.sleep((long) (Math.random() * 3000));
            System.out.println(id + " 號遊客到達集合點,等待其他人...");
            
            int arrivalOrder = barrier.await(); // 到達屏障點等待
            System.out.println(id + " 號遊客是第 " + (arrivalOrder + 1) + " 個到達的");
            
        } catch (InterruptedException | BrokenBarrierException e) {
            Thread.currentThread().interrupt();
            System.err.println(id + " 號遊客行程中斷:" + e.getMessage());
        }
    }
}

public class SpringOuting {
    public static void main(String[] args) {
        int touristCount = 10;
        
        // 攜帶攔截動作:所有人到齊後自動執行
        CyclicBarrier barrier = new CyclicBarrier(touristCount, () -> {
            System.out.println("======== 所有人到齊,一起出發!========");
        });

        for (int i = 1; i <= touristCount; i++) {
            new Thread(new Tourist(i, barrier)).start();
        }
    }
}

輸出範例

3 號遊客到達集合點,等待其他人...
1 號遊客到達集合點,等待其他人...
7 號遊客到達集合點,等待其他人...
5 號遊客到達集合點,等待其他人...
2 號遊客到達集合點,等待其他人...
9 號遊客到達集合點,等待其他人...
4 號遊客到達集合點,等待其他人...
6 號遊客到達集合點,等待其他人...
10 號遊客到達集合點,等待其他人...
8 號遊客到達集合點,等待其他人...
======== 所有人到齊,一起出發!========
8 號遊客是第 1 個到達的
10 號遊客是第 2 個到達的
...

深度對比:CountDownLatch vs CyclicBarrier

維度CountDownLatchCyclicBarrier
核心語義倒數計數,等待事件完成攔截匯合,等待線程到達
可重用性不可重用(計數歸零失效)可重用(reset() 重置)
線程角色一線程等多線程 / 多線程等一線程多線程互相等待(對等關係)
攔截動作不支援支援 barrierAction(最後到達者執行)
返回值無返回到達序號(0 為最後)
異常處理僅 InterruptedExceptionInterruptedException + BrokenBarrierException
實現基礎AQS 共享鎖ReentrantLock + Condition

進階用法:分階段計算

// 多階段並行計算,每階段同步
CyclicBarrier barrier = new CyclicBarrier(workerCount, () -> {
    // 階段合併結果
    mergePhaseResults();
});

for (int phase = 0; phase < totalPhases; phase++) {
    // 並行計算當前階段
    executePhase(phase);
    
    try {
        barrier.await(); // 等待所有線程完成本階段
    } catch (InterruptedException | BrokenBarrierException e) {
        handleError(e);
    }
}

故障恢復與 BrokenBarrierException

  • 任一線程 await() 過程中被中斷/超時 → 所有等待線程拋出 BrokenBarrierException
  • 屏障進入「損壞狀態」,需調用 reset() 恢復
  • 生產代碼必須捕獲並處理此異常,避免線程池任務靜默失敗

適用場景總結

  • 多線程分階段計算(MapReduce 風格)
  • 並行測試中多客戶端同步發壓
  • 遊戲副本/房間等待滿員開始
  • 多服務啟動依賴檢查同步
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved