cyclicbarrier用于多线程协同到达同步点后集体放行,可重复使用;构造时指定线程数,调用await()等待全员到达,支持回调、超时及异常处理,适用于循环赛跑等场景。

Java 中用 CyclicBarrier 实现多线程“赛跑”并统一在某个同步点等待,核心是让多个线程各自执行任务,到达同一道“终点线”后集体放行——它不像 CountDownLatch 那样只能用一次,而是可重复使用,适合循环场景(比如多轮比赛)。
理解 CyclicBarrier 的基本用法
CyclicBarrier 是一个同步辅助类,构造时指定参与线程数(即“参赛人数”),每个线程调用 await() 方法表示自己已到达屏障点。当指定数量的线程都调用了 await(),所有线程才同时被唤醒继续执行;若未满员,调用者会阻塞等待。
- 构造方式:
new CyclicBarrier(4)表示需 4 个线程全部到达才放行 - 可选传入
Runnable:在最后第 N 个线程到达时、放行前,由该线程执行一次(常用于发令、日志或初始化) - 支持超时:
await(5, TimeUnit.SECONDS)避免某线程挂起导致整体死等
模拟多线程赛跑的典型代码结构
假设 4 位选手(线程)从起点出发,各自随机耗时跑完,然后在终点集合,一起宣布“本轮结束”。关键在于每个线程独立运行,但必须等齐才进入下一阶段。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
CyclicBarrier barrier = new CyclicBarrier(4, () -> {
System.out.println("✅ 所有人到齐!开始下一轮");
});
<p>for (int i = 0; i {
try {
System.out.println("?♂️ 运动员 " + runnerId + " 开始起跑");
Thread.sleep((long) (Math.random() * 2000) + 1000); // 模拟不同耗时
System.out.println("? 运动员 " + runnerId + " 到达终点");
barrier.await(); // 抵达屏障点,等待其他人
System.out.println("? 运动员 " + runnerId + " 进入颁奖环节");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}</p>
处理异常与中断的注意事项
await() 可能抛出 InterruptedException(线程被中断)、BrokenBarrierException(屏障被破坏,比如某线程超时退出或被中断,导致其他线程无法正常等待)。实际使用中建议:
- 捕获
BrokenBarrierException后通常应重新检查状态,或放弃本轮逻辑 - 若某线程因异常提前退出,屏障会被标记为“破损”,后续调用
await()会立即抛BrokenBarrierException - 可通过
barrier.reset()重置屏障(慎用,需确保无线程正在 await)
对比 CountDownLatch 和 Phaser 的适用场景
别把 CyclicBarrier 当成万能同步工具:
- 和
CountDownLatch不同:后者是一次性“倒计时门”,适合“主线程等子任务完成”;而CyclicBarrier是“全员互相等”,适合协同推进的循环任务 - 和
Phaser相比:后者更灵活(可动态增减参与者、分阶段、支持层级),但复杂度高;简单固定人数的“赛跑”场景,CyclicBarrier更轻量直观
不复杂但容易忽略:屏障点不是“谁先到谁先走”,而是“谁最后到,谁触发全体通行”。设计时注意线程任务耗时差异,避免因个别线程卡顿拖慢全局节奏。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










