news 2026/7/15 5:46:51

并发三剑客:CountDownLatch、Semaphore 与 CyclicBarrier 的奇妙旅行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
并发三剑客:CountDownLatch、Semaphore 与 CyclicBarrier 的奇妙旅行

背景设定

想象你正在组织一场大型旅游活动。这场旅行涉及多个环节——游客集合、上车出发、景点游览、集体拍照、返程下车……每个环节都需要多人协作、同步进行。而 Java 并发包里的这三个工具类,就像三位各司其职的“旅行协调员”,分别负责不同的任务节奏控制。


第一章:CountDownLatch —— “等所有人干完活再收工”的监工

🧑‍💼 角色定位:一次性任务汇总员

在旅行前,你需要先为每位游客计算专属优惠价格(比如根据会员等级打折)。这项工作由10个后台线程并行完成——每个线程负责一个游客的价格计算。

但你不能提前宣布“价格算好了”,必须等所有10个人都算完才行。

这时候,你就请来了CountDownLatch这位“一次性监工”。

🔧 工作方式:

  • 你一开始就说:“我要等10个人完成任务。” →new CountDownLatch(10)
  • 每个线程算完自己的部分,就喊一声:“我搞定了!” → 调用countDown()
  • 主线程站在门口等着,直到听到第10声“搞定” →await()返回,继续下一步
CountDownLatchlatch=newCountDownLatch(10);// 启动10个线程计算价格...latch.await();// 阻塞,直到所有线程调用 countDown()System.out.println("所有价格计算完毕,可以出票了!");

⚠️ 特点:

  • 只能用一次:一旦计数归零,就不能再重置。就像监工交差后就下班了。
  • 适合“多对一”同步:多个子任务完成后,通知主线程继续。

适用场景:初始化资源、并行任务汇总、测试等待所有线程就绪。


第二章:Semaphore —— “限流闸机”的守门人

🧑‍💼 角色定位:并发流量控制器

现在游客要进入景区了!但景区规定:同一时间最多只能有5人进入,否则会拥挤。

于是你请来Semaphore这位“守门人”,他手里拿着5张“入场券”(许可证)。

🔧 工作方式:

  • 初始发放5张券 →new Semaphore(5)
  • 游客想进?先领一张券 →acquire()
    • 如果还有券,立刻进入;
    • 如果没券了,就在门口排队等别人出来。
  • 游客离开时,把券还回去 →release(),下一个人就能进
Semaphoregate=newSemaphore(5);// 最多5人同时进入newThread(()->{gate.acquire();// 申请进入System.out.println("游客进入景区...");Thread.sleep(2000);gate.release();// 离开,归还许可}).start();

⚠️ 特点:

  • 可重复使用:券用完还能回收再发。
  • 支持公平/非公平模式:默认“谁抢到谁进”(非公平),也可改成“先到先得”(公平)。
  • 不限定具体线程:任何线程都能申请或释放许可。

适用场景:数据库连接池、API限流、限制同时在线用户数。


第三章:CyclicBarrier —— “全员到齐才出发”的导游

🧑‍💼 角色定位:循环协同触发器

现在到了最关键的环节:全团必须一起上车,一起下车

你有10位游客 + 1位导游,共11人。只有当所有人都坐上车,大巴才能启动;同样,所有人都下车后,才算行程结束。

这时,你请来了CyclicBarrier这位“循环导游”。

🔧 工作方式:

  • 设定人数:11人 →new CyclicBarrier(11)
  • 每个人上车后喊一声:“我上车了!” → 调用await()
  • 前10个人喊完,会被阻塞在车上等待;
  • 第11个人(比如导游)喊完,所有人同时被释放,车子启动!
  • 更神奇的是:下车时再用同一个 barrier,它还能再用一次
CyclicBarrierbarrier=newCyclicBarrier(11);// 每个游客线程:barrier.await();// 上车等待System.out.println("游客X上车");// 导游也 await()barrier.await();// 此刻全员释放,车开动!// 后续还能再次用于“下车同步”

⚠️ 特点:

  • 可循环使用:一次屏障解除后,自动重置,下次还能用。
  • 支持回调动作:可以在全员到齐时执行一个任务(比如发车前检查安全带)。
  • 所有参与者平等:没有“主线程 vs 子线程”之分,大家都是 await 的一员。

适用场景:多线程模拟、并行计算分阶段同步、游戏回合制同步。


第四章:三人对比 —— 谁该在什么时候出场?

工具谁在等?谁在动?能不能重用?典型比喻
CountDownLatch主线程等子线程子线程干完就走❌ 一次性监工验收工程
Semaphore线程等许可任意线程申请/释放✅ 可重用景区限流闸机
CyclicBarrier所有线程互相等全员协同行动✅ 可循环导游喊“人齐了没?”

🎯 使用建议:

  • 等一堆任务做完再继续?→ 选CountDownLatch
  • 限制同时干活的人数?→ 选Semaphore
  • 让一群人步调一致、分阶段行动?→ 选CyclicBarrier

尾声:并发世界的秩序之美

在看似混乱的多线程世界里,正是这些精巧的同步工具,让程序像一支训练有素的旅行团——

有人负责汇总进度,有人控制人流,有人确保全员同步。

它们不争不抢,各司其职,共同维护着并发世界的秩序与效率。

下次当你面对复杂的线程协作问题时,不妨问问自己:

“我现在需要的是监工、守门人,还是导游?”

答案,就在你的业务场景之中。


希望这个“旅行故事”让你对这三个并发工具的理解更生动、更牢固!

详细代码解读请看Semaphore&CountDownlatch&CyclicBarrier源码分析

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/7 21:38:39

5分钟部署Whisper语音识别:零基础搭建多语言转录服务

5分钟部署Whisper语音识别:零基础搭建多语言转录服务 引言:语音识别原来这么简单 你有没有遇到过这样的场景?会议录音需要整理成文字,外语视频需要翻译字幕,或者想给音频内容添加文字说明。传统方法要么手动打字费时…

作者头像 李华
网站建设 2026/7/7 21:42:41

VMD-SE-BiLSTM+Transformer多变量时序预测,MATLAB代码

一、研究背景 该模型针对复杂非线性时间序列预测问题,特别是具有多尺度、非平稳特性的时序数据。传统单一模型难以同时捕捉时序数据中的低频趋势和高频波动特征,因此采用分解-重构-混合建模 的策略,结合信号处理与深度学习技术提升预测精度。…

作者头像 李华
网站建设 2026/7/7 21:42:27

局域网中两台win电脑传输文件

文章目录1.方案一:Python 一行命令 HTTP 服务 (最接近 Linux 体验)1. 在发送方电脑 A 上操作2. 在接收方电脑 B 上操作2.方案二:Windows 共享文件夹 (适合频繁传输)3. Linux电脑向Win电脑传输文件总结✨✨✨学习的道路很枯燥,希望我们能并肩走…

作者头像 李华
网站建设 2026/7/7 21:42:58

Flink运行架构深度解析:从核心组件到实战提交

一、Flink运行架构概述Flink作为一个分布式流式计算引擎,其运行架构主要围绕 JobManager 和 TaskManager 两大核心组件展开。1. JobManager(Master)负责协调分布式任务的执行,包括任务调度、资源申请、检查点协调和故障恢复等。一…

作者头像 李华
网站建设 2026/7/7 21:42:40

如何选择高安全性CDN服务?2026年五大厂商深度横评指南

在数字化时代,CDN 作为业务内容分发的核心基础设施,其安全性直接决定了企业数据传输与业务运营的稳定性,选择一家高安全性的 CDN 服务公司成为企业数字化布局的关键。本文从合规资质、传输加密、访问控制、运维与服务四大核心维度&#xff0c…

作者头像 李华
网站建设 2026/7/7 21:42:40

数位差与数值和的构造

求解代码public static void main(String[] args) throws IOException {BufferedReader br new BufferedReader(new InputStreamReader(System.in));StringTokenizer in new StringTokenizer(br.readLine());PrintWriter out new PrintWriter(new OutputStreamWriter(System…

作者头像 李华