cyclicbarrier 是可重用的多线程同步工具,支持分阶段协作:所有线程调用 await() 阻塞,待指定数量线程到达后,由最后一个线程执行 barrieraction(如汇总),再同时释放全部线程。

CyclicBarrier 是 Java 并发包(java.util.concurrent)中用于多线程**同步等待、分阶段协作**的工具。它特别适合“多个线程各自执行一段任务 → 全部到达某个屏障点 → 一起继续下一阶段”的场景,比如分片计算后汇总结果。
理解 CyclicBarrier 的核心行为
它不像 CountDownLatch 那样只能用一次;CyclicBarrier 可重用(cyclic),所有线程调用 await() 后会阻塞,直到指定数量的线程都到达,才同时释放全部线程,并可选择执行一个“屏障动作”(Runnable)——这个动作由**最后一个到达的线程触发,且在所有线程被释放前执行**,非常适合做阶段汇总。
分阶段计算 + 汇总的关键步骤
- 创建 CyclicBarrier 时传入参与线程数,以及一个 barrierAction(即汇总逻辑)
- 每个工作线程完成自己的局部计算后,调用
barrier.await() - 当第 N 个线程调用 await,屏障被触发:先执行 barrierAction(汇总),再唤醒所有线程进入下一阶段
- 如果需要多轮分阶段(如迭代计算),CyclicBarrier 可重复使用,无需重建
一个典型示例:4 个线程分别计算数组子段和,每轮结束后汇总总和
假设有一个长度为 100 的整型数组,4 个线程各负责 25 个元素求和;每轮计算完,把 4 个局部和加总到全局变量中:
// 共享变量,用于存放每轮汇总结果
private static volatile long totalSum = 0;
<p>public static void main(String[] args) {
int[] data = new Random().ints(100, 1, 11).toArray(); // 100 个 1~10 的随机数
int numThreads = 4;
CyclicBarrier barrier = new CyclicBarrier(numThreads, () -> {
// barrierAction:仅由最后一个到达的线程执行,安全地汇总
System.out.println("✅ 所有线程完成本轮计算,开始汇总...");
// 注意:此处无竞争,因只由单线程执行
System.out.println("本轮汇总结果:" + totalSum);
totalSum = 0; // 重置,为下一轮准备(若需迭代)
});</p><pre class="brush:java;toolbar:false;">List<thread> workers = new ArrayList();
int segmentSize = data.length / numThreads;
for (int i = 0; i {
long localSum = 0;
for (int j = startIndex; j {
try { t.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});</thread>}
注意事项与常见陷阱
- 屏障动作(barrierAction)不能耗时过长,否则会阻塞所有线程释放,影响整体吞吐
-
异常处理必须覆盖:
BrokenBarrierException表示屏障被中断或重置;InterruptedException需恢复中断状态 - 若某线程在 await 前抛异常或被中断,屏障会被打破,其余线程 await 会立即抛
BrokenBarrierException - 想在 barrierAction 中访问各线程的局部结果?CyclicBarrier 本身不传递数据 —— 可配合 共享容器(如 AtomicIntegerArray、ConcurrentHashMap)或 ThreadLocal + 全局注册 实现
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











