原文来自于:[zha-ge.cn/java/75http…

Java CyclicBarrier 详解:原理、使用方式与应用场景

说起来多线程,真的是一把双刃剑,玩的爽的时候效率飞起,踩坑的时候能让你想砸键盘。那天被产品催着搞个并发汇总批量处理,“必须所有线程都处理完才能出最终结果哈!”老板一句话,我心里mmp冒了三句,然后想到了老朋友——CyclicBarrier。

那些年被读写锁捣鼓晕了

先给没见过 CyclicBarrier 的朋友科普一句,它的意思其实就是“循环栅栏”,就像个闸门——得等所有小伙伴都到了门口,门一开大家再齐头并进。所以它适用于那种“大家一起做点事,等大家都干完才能继续”的场合。

一开始你可能想:“我用 CountDownLatch 不就行?”确实,俩有点像。但 CyclicBarrier 能用多轮,Latch 一次性的,完事就没法再用了。

突发奇想用 CyclicBarrier 干票大的

我的场景是这样:假如有三个子线程,必须等它们都到齐,聚在一起后,才能合体出最终报告。伪代码像这样:

CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("大家一起出发!"));

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        // 各自干各自的活
        doSomething();
        try {
            barrier.await(); // 等到小伙伴都到了
        } catch (Exception e) {
            // 啊又爆炸了!
        }
        // 继续后续操作
    }).start();
}

哪怕你有 30 个线程也照样安排,只要前面数字一样,线程就小学生排队似的,你来我来大家一起闯关。

踩坑瞬间

别以为 CyclicBarrier 就完美了哈!我第一次用的时候,线程里有个“不小心”抛了个 Exception,结果整个 barrier.await 就等到天荒地老。啥原因?原来只要有一个 thread 异常退出了,其他的就都被冻那了——barrier 一直等不到齐活。

总结几个坑点:

  • 有一个线程异常退出,整个 barrier 卡死,剩下的线程永远等不来 release。
  • 重复利用 CyclicBarrier 时,记住 barrier.reset() 是把大家拉回起跑线,但正在等待的那帮线程会直接收到异常(BrokenBarrierException),得做好异常处理。
  • 提前触发 barrier 任务(那第二个参数 Runnable),如果任务失败也会导致大家全都抛异常。

举个踩坑代码片段,全靠经验教训:

try {
    barrier.await();  // 这里如果线程提前崩了,剩下的人就直接 BrokenBarrierException了
} catch (BrokenBarrierException | InterruptedException e) {
    // 做好善后,不然你得加班写年终总结……
}

CyclicBarrier 最妙的感觉

用完 CyclicBarrier,我体会到最美的一刻就是三个线程像打卡上班,一起蹲在门口,等班长(barrier任务)发指令,然后啪,一起冲。特别适合:

  • 多个线程数据计算,最后聚合
  • 分段下载,等分块都好了再合成
  • 测试场景下模拟“大部队”同时开火

别的场景你也可以“想歪用一下”,比如刷队伍小游戏(拼手速),别愣着,场景绝对取之不尽。

经验启示

又到了填鸡汤瓶的时间——自己亲身试过后,才发现:

  • CyclicBarrier 爱凑数儿,线程数对不上就没得玩
  • 一定要处理异常,尤其是 BrokenBarrierException
  • 它循环可重用,比 CountDownLatch 强在玩多轮赛
  • barrier内部有个“小小黑屋”(generation),重置和异常都会让大家被踢出来,记得写好兜底

最后送你一张我的偷懒手册:

关键点记忆口诀
对线程数有要求人没到齐,门不开
适合多轮齐步走一拨儿走完还能再来一拨
异常要特别留意讹出一个,全员搁浅

溜了溜了……

写的累,但 CyclicBarrier 用顺了是真香。前提是你真知道自己要的啥,别上线了一堆线程尬等。对了,如果你也踩过啥多线程的坑,评论里一起唠嗑,帮我打打气,下次再写点更野的故事!

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]