cyclicbarrier 是 java 并发包中支持多轮重复协作的同步工具,可重用且能在所有线程到达后执行屏障动作;需指定参与线程数 parties,调用 await() 阻塞等待,任一线程中断将导致屏障破损。

CyclicBarrier 是 Java 并发包(java.util.concurrent)中用于协调多个线程在某个“屏障点”同步等待的工具。它特别适合需要**多轮重复协作**的场景,比如分批次处理数据、多线程并行计算后汇总、模拟循环赛制等。与 CountDownLatch 不同,CyclicBarrier 可重用(cyclic),且支持在所有线程到达后执行一个可选的“屏障动作”(Runnable)。
核心原理与关键参数
构造一个 CyclicBarrier 至少需要指定参与线程数(即“ parties ”):
-
CyclicBarrier(int parties):当parties个线程都调用await()后,全部被唤醒,继续执行; -
CyclicBarrier(int parties, Runnable barrierAction):在最后第parties个线程到达时,由该线程**串行执行**barrierAction,再释放所有线程; - 调用
await()的线程会阻塞,直到满足条件或被中断/超时; - 任一线程在
await()中被中断,屏障将被打破(broken),后续调用await()会立即抛出BrokenBarrierException。
基本使用示例:三线程协同完成一轮任务
假设 3 个工人线程各自加工一个零件,必须等三人全部完工才一起进入下一道工序(如组装):
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("✅ 所有零件就绪,开始组装...");
});
<p>for (int i = 0; i {
System.out.println(Thread.currentThread().getName() + " 开始加工零件");
try {
Thread.sleep(1000 + (long)(Math.random() * 2000)); // 模拟耗时不同
System.out.println(Thread.currentThread().getName() + " 加工完成");
barrier.await(); // 到达屏障点,等待其他人
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}, "Worker-" + i).start();
}</p>输出类似:
Worker-0 开始加工零件 Worker-1 开始加工零件 Worker-2 开始加工零件 Worker-1 加工完成 Worker-0 加工完成 Worker-2 加工完成 ✅ 所有零件就绪,开始组装...
支持多轮循环:重用 barrier 实现批次处理
因为 CyclicBarrier 是可重用的,同一实例可在多轮中反复使用。例如每轮处理 4 个任务,共进行 2 轮:
- 创建
CyclicBarrier barrier = new CyclicBarrier(4);; - 启动 4 个线程,每个线程执行一次任务后
await(); - 4 线程全部 await 返回后,本轮结束;
- 紧接着再次启动 4 个新线程(或复用线程池),再次调用
await()—— barrier 自动进入下一轮; - 注意:若某轮中发生异常导致屏障 broken,需调用
reset()恢复(但会中断所有正在 await 的线程)。
实用技巧与注意事项
-
避免死锁:确保每个参与线程最终都会调用
await(),否则其余线程永久阻塞; -
超时控制:使用
await(long timeout, TimeUnit unit)防止个别线程卡死,超时抛出TimeoutException; -
异常传播:屏障动作(
barrierAction)中抛出未捕获异常,会导致屏障 broken,后续 await 失败; -
与线程池配合:推荐用
ExecutorService提交任务,而非手动 new Thread,更易管理; -
状态判断:可通过
isBroken()或getNumberWaiting()辅助调试(仅限开发/测试阶段)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











