CyclicBarrier 是可重用的多线程分阶段同步工具,通过内部计数器协调指定数量线程在屏障点等待并统一推进,支持屏障动作、超时控制和异常处理,适用于平等协作场景。

CyclicBarrier 是 Java 并发包中用于多线程分阶段同步的利器,它能让一组线程在到达某个“屏障点”时互相等待,全部到齐后才一起继续执行下一阶段——而且这个过程可以重复使用(即“循环”)。
理解 CyclicBarrier 的核心机制
CyclicBarrier 内部维护一个计数器,初始化时指定参与同步的线程总数(parties)。每个线程调用 await() 方法即表示自己已到达当前阶段;该方法会阻塞,直到有足够数量的线程都调用了 await()。一旦计数器归零,所有等待线程被唤醒,并可选择性地执行一个由构造时传入的 Runnable 任务(屏障动作),常用于汇总、校验或准备下一阶段数据。
与 CountDownLatch 不同,CyclicBarrier 可重置、可复用:当所有线程通过一次后,计数器自动重置为初始值,下一轮同步可立即开始。
基本用法:三步完成分阶段同步
- 创建 CyclicBarrier:指定线程总数(如 4 个 worker),并可选传入 barrierAction(例如日志记录或结果合并)
- 各线程执行本阶段任务:比如读取数据、计算局部结果、写临时文件等
- 统一调用 await():阻塞直至全部线程就位;返回后进入下一阶段逻辑
实战示例:模拟四阶段数据处理流水线
假设有 3 个 Worker 线程,需协作完成 2 轮「采集 → 预处理 → 分析 → 汇总」流程:
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("✅ 所有线程完成本阶段,进入下一阶段");
});
for (int round = 0; round < 2; round++) {
ExecutorService exec = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
exec.submit(() -> {
// 阶段1:采集
System.out.println("? 采集数据...");
try { barrier.await(); } catch (Exception e) {}
// 阶段2:预处理
System.out.println("⚙️ 预处理中...");
try { barrier.await(); } catch (Exception e) {}
// 阶段3:分析
System.out.println("? 分析模型...");
try { barrier.await(); } catch (Exception e) {}
// 阶段4:汇总(屏障动作已在上一轮触发)
System.out.println("? 本地汇总完成");
});
}
exec.shutdown();
exec.awaitTermination(10, TimeUnit.SECONDS);
}
输出会呈现清晰的阶段对齐效果:所有线程先打印“?”,再同时打印“⚙️”,依此类推——体现严格分阶段同步。
关键细节与避坑提醒
- 异常处理不可忽略:await() 抛出 InterruptedException 或 BrokenBarrierException,必须捕获;若任一线程中断或超时,屏障会被打破,其他线程 await() 将抛出 BrokenBarrierException
- 超时控制更健壮:使用 await(long timeout, TimeUnit unit) 避免永久阻塞,适合存在耗时不确定任务的场景
- 重置屏障需谨慎:调用 reset() 会强制唤醒所有等待线程并清空状态,适用于异常恢复,但会丢失当前轮次上下文
- 不适用于主从模式:CyclicBarrier 假设所有参与者地位平等;若需“一个主线程等多个子线程”,CountDownLatch 更自然

















