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

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

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

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

那些年被读写锁捣鼓晕了

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

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

突发奇想用 CyclicBarrier 干票大的

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

java 复制代码
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),如果任务失败也会导致大家全都抛异常。

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

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

CyclicBarrier 最妙的感觉

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

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

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

经验启示

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

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

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

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

溜了溜了......

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

相关推荐
神明不懂浪漫1 分钟前
【第五章】Java中的继承与多态
java·开发语言
AI多Agent协作实战派2 小时前
AI多Agent协作系统实战(十七):凌晨4点,我的AI系统在“假装工作“——3个bug同时爆炸的5小时
java·前端·bug
gaolei_eit2 小时前
Java+Ai+vue
java·spring·maven
qq_2518364572 小时前
基于java Web 动漫视频网站毕业论文
java·开发语言·前端
LayZhangStrive2 小时前
JUC相关的函数、注解、变量杂记
java·面试·多线程·juc
未秃头的程序猿2 小时前
给公司做了个AI客服Agent,用的Spring AI 1.0,3天上线领导拍板了
java·后端·ai编程
曹牧2 小时前
Eclipse 批量文本替换
java·ide·eclipse
程序员清风3 小时前
OpenAI官方发布最新提示词技巧!
java·后端·面试
一只枫林3 小时前
MySQL内、外连接知识点汇总
java·前端·数据库
梅头脑3 小时前
写了3年CRUD,volatile和synchronized的区别还是答不清——直到我画出了这张三性两锁边界图
java