CyclicBarrier详解

CyclicBarrier 是 Java 并发工具类,基于屏障点(Barrier)实现多线程协同等待。通过 await() 阻塞线程直至所有线程到达屏障,支持重置和屏障后动作。常用于分阶段任务或并行计算结果的合并。


一、核心功能

  1. 协同等待:多个线程互相等待,直到全部到达屏障点后继续执行。
  2. 可重用性:计数器可重置,支持多次任务分阶段执行。
  3. 屏障后动作 :所有线程到达屏障后,可触发自定义的 Runnable 任务(如合并结果)。

二、核心方法

方法 说明
CyclicBarrier(int parties) 构造方法,指定等待的线程数
CyclicBarrier(int parties, Runnable barrierAction) 指定线程数和屏障后触发的任务
int await() 阻塞当前线程,直到所有线程到达屏障
int await(long timeout, TimeUnit unit) 带超时的等待,超时抛出 TimeoutException
void reset() 重置屏障,未到达的线程将抛出 BrokenBarrierException
int getParties() 获取屏障需要的线程数
int getNumberWaiting() 获取当前等待的线程数

三、典型使用场景

  1. 多阶段任务
    例如:分批次处理数据,每批所有线程处理完成后进入下一阶段。
  2. 并行计算合并
    例如:多个线程分别计算部分结果,所有线程完成后汇总最终结果。
  3. 模拟测试
    让多个线程在特定阶段同步,观察并发行为。

四、代码示例

java 复制代码
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        int threadCount = 3;
        // 定义屏障后的汇总任务
        Runnable mergeAction = () -> System.out.println("所有线程到达屏障,开始合并结果...");
        
        CyclicBarrier barrier = new CyclicBarrier(threadCount, mergeAction);

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                try {
                    System.out.println("线程计算中...");
                    Thread.sleep(1000);
                    barrier.await(); // 等待其他线程
                    System.out.println("线程继续执行后续任务...");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

五、注意事项

  1. 线程阻塞
    await() 会阻塞线程,若线程池中工作线程数不足,可能导致死锁。
  2. 异常处理
    若有线程在等待时被中断或超时,屏障将损坏(BrokenBarrierException),需调用 reset() 重置。
  3. 屏障动作执行
    屏障后的 Runnable 任务由最后到达屏障的线程执行,其他线程继续前需等待该任务完成。
  4. 重置风险
    reset() 会立即打破当前屏障,可能导致未到达的线程抛出异常,需谨慎使用。

六、对比 CountDownLatch

特性 CyclicBarrier CountDownLatch
重用性 支持重置,可重复使用 一次性
核心角色 多线程互相等待 主线程等待子线程或子线程等待主线程
触发条件 所有线程到达屏障点 计数器归零
附加任务 支持屏障后执行自定义任务

七、高级用法

1. 分阶段任务

java 复制代码
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("阶段完成,进入下一阶段"));
// 多线程分阶段执行任务
for (int stage = 1; stage <= 3; stage++) {
    new Thread(() -> {
        doStageWork(stage);
        barrier.await(); // 等待所有线程完成当前阶段
    }).start();
}

2. 处理屏障损坏

java 复制代码
try {
    barrier.await();
} catch (BrokenBarrierException e) {
    System.out.println("屏障已损坏,需重置或终止任务");
    barrier.reset(); // 重置屏障
}

总结
CyclicBarrier 适用于多线程分阶段协同工作的场景,通过可重用性和屏障后任务简化复杂同步逻辑。与 CountDownLatch 不同,它强调线程间的对等协作而非单向依赖。

相关推荐
PH = 738 分钟前
OverlayFS联合文件系统使用示例
java·linux·服务器
AC赳赳老秦1 小时前
OpenClaw进阶技巧:批量修改文件内容、替换关键词,解放双手
java·linux·人工智能·python·算法·测试用例·openclaw
Java小白笔记1 小时前
OpenClaw 实战方法论
java·开发语言·人工智能·ai·全文检索·ai编程·ai写作
呱牛do it1 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 5)
java·vue
练习时长一年1 小时前
Spring配置类的演化
java·spring boot·spring
喜欢流萤吖~2 小时前
服务间的依赖管理:微服务的协作之道
java·微服务
invicinble2 小时前
Spring如何把bean注册到容器里
java·后端·spring
代码不加糖2 小时前
0基础搭建前后端分离项目:实现菜单与界面左右布局
java·前端·javascript·mysql·elementui·mybatis
希望永不加班2 小时前
SpringBoot 敏感数据脱敏(序列化层)
java·spring boot·后端·spring
希望永不加班2 小时前
SpringBoot 数据库索引优化:慢查询分析
java·数据库·spring boot·后端·spring