CyclicBarrier 是 Java 并发包中用于多线程阶段性同步的可重用工具,支持指定线程数、屏障动作、超时等待及异常处理,适用于固定规模的分阶段协作场景。

CyclicBarrier 是 Java 并发包(java.util.concurrent)中用于多线程**阶段性同步**的核心工具之一。它让一组线程在到达某个“屏障点”时相互等待,直到全部线程都到达后才一起继续执行——非常适合分阶段协作的场景,比如并行计算的多个子任务完成后统一汇总、模拟多角色协同启动等。
理解 CyclicBarrier 的核心行为
与 CountDownLatch 不同,CyclicBarrier 是可重用的(cyclic),且关注的是“所有线程同时抵达后放行”,而非“等待一个事件完成”。它的关键特性包括:
- 构造时指定参与线程数(
parties),即需要多少个线程调用await()才能触发释放 - 任意线程调用
await()后会被阻塞,直到其他线程也陆续调用await()补齐人数 - 当最后一个线程调用
await()时,所有线程被同时唤醒,继续向下执行 - 可选传入一个
Runnable作为“屏障动作”(barrier action),由最后一个到达的线程在释放前执行(常用于汇总、日志、状态检查等) - 支持超时等待(
await(long timeout, TimeUnit unit)),避免因某线程异常导致全体卡死
典型使用步骤:三步构建阶段性同步
以“4 个工人并行加工零件,每轮加工完需共同质检后再进入下一轮”为例:
-
1. 创建 CyclicBarrier 实例:
CyclicBarrier barrier = new CyclicBarrier(4, () -> System.out.println("✅ 全部完成,开始质检..."));
这里 4 表示需 4 个线程到达,lambda 是质检逻辑(仅由最后到的线程执行一次) -
2. 每个线程在阶段末尾调用 await():
在各自加工逻辑后插入barrier.await();。若任一线程中断或超时,屏障会破溃(broken),后续调用将抛BrokenBarrierException -
3. 处理异常与重用:
在await()外包裹 try-catch,捕获InterruptedException、BrokenBarrierException和TimeoutException;
若未破溃,屏障可重复使用(如进入下一轮加工),无需重建
实战代码片段(带错误处理与重用)
以下是一个可运行的简化示例:
立即学习“Java免费学习笔记(深入)”;
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("? 阶段一结束,汇总数据...");
});
<p>for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 开始阶段一任务");
Thread.sleep(500 + (long)(Math.random() * 500)); // 模拟不同耗时
System.out.println(Thread.currentThread().getName() + " 完成阶段一");</p><pre class='brush:php;toolbar:false;'> barrier.await(); // 等待其他线程
System.out.println(Thread.currentThread().getName() + " 进入阶段二");
Thread.sleep(300);
} catch (InterruptedException | BrokenBarrierException e) {
System.err.println(Thread.currentThread().getName() + " 被中断或屏障异常: " + e.getMessage());
}
}, "Worker-" + i).start();}
输出中你会看到:3 个 Worker 完成时间不同,但都停在 await() 处;等最后一个到达,屏障动作执行,然后 3 个线程才几乎同时打印“进入阶段二”——这就是阶段性同步的效果。
注意事项与避坑提示
-
屏障破溃(broken)后不可恢复:一旦发生中断、超时或屏障动作抛异常,
isBroken()返回 true,后续await()会立即抛BrokenBarrierException;需调用reset()重置(但会唤醒所有等待线程并抛异常),或新建实例 - 屏障动作不要耗时或阻塞:它由最后一个到达线程串行执行,若太慢会拖慢全体进度
-
慎用共享变量做屏障条件:CyclicBarrier 本身不保证内存可见性,若需依赖其他线程写入的状态,应在
await()前加volatile或显式同步 -
和 Phaser 对比:若需动态增减参与者、分层屏障或更细粒度控制,建议改用
Phaser;CyclicBarrier 更适合固定规模、结构清晰的阶段同步



















