当前位置: 首页 > news >正文

Java中的并发工具类CountDownLatch,CyclicBarrier,Semaphore

Java中的并发工具类CountDownLatch,CyclicBarrier,Semaphore

CountDownLatch(倒计时门闩)

核心作用:一个或多个线程等待其他线程完成一系列操作后,再继续执行

  • 基于 “计数器” 实现:初始化时指定一个计数(需等待的事件数量)。
  • 当一个线程完成任务后,调用 countDown() 方法让计数减 1。
  • 等待的线程通过 await() 方法阻塞,直到计数减为 0 时被唤醒,继续执行。

特点

  • 计数一旦到 0,就不可重置(一次性使用)。
  • 适用于 “一对多” 或 “多对多” 的等待场景(如主线程等待多个子线程初始化完成)。

image-20251006213715971

场景示例

用户下了一个外卖订单,包含 宫保鸡丁、鱼香肉丝、麻婆豆腐 三道菜(对应 “数据源”)。

  • 线程 1(厨师 A):负责做宫保鸡丁,做完后调用 countDown()
  • 线程 2(厨师 B):负责做鱼香肉丝,做完后调用 countDown()
  • 线程 3(厨师 C):负责做麻婆豆腐,做完后调用 countDown()
  • 汇总线程(骑手):需要等三道菜都做好(cdl.await()),才能取餐配送(“对三道菜汇总打包”)。

代码生成

import java.util.concurrent.CountDownLatch;public class TakeawayDemo {public static void main(String[] args) {// 初始化计数器为3(需要等待3道菜做好)CountDownLatch mealLatch = new CountDownLatch(3);// 厨师A:做宫保鸡丁Thread chefA = new Thread(() -> {try {System.out.println("厨师A开始做宫保鸡丁...");Thread.sleep(2000); // 模拟做菜耗时System.out.println("厨师A:宫保鸡丁做好了!");} catch (InterruptedException e) {e.printStackTrace();} finally {// 菜做好,计数器减1mealLatch.countDown();}});// 厨师B:做鱼香肉丝Thread chefB = new Thread(() -> {try {System.out.println("厨师B开始做鱼香肉丝...");Thread.sleep(1500); // 模拟做菜耗时System.out.println("厨师B:鱼香肉丝做好了!");} catch (InterruptedException e) {e.printStackTrace();} finally {mealLatch.countDown();}});// 厨师C:做麻婆豆腐Thread chefC = new Thread(() -> {try {System.out.println("厨师C开始做麻婆豆腐...");Thread.sleep(1000); // 模拟做菜耗时System.out.println("厨师C:麻婆豆腐做好了!");} catch (InterruptedException e) {e.printStackTrace();} finally {mealLatch.countDown();}});// 骑手:等待所有菜做好后取餐Thread rider = new Thread(() -> {try {System.out.println("骑手已到达餐厅,等待所有菜品完成...");// 阻塞等待,直到计数器归0mealLatch.await();System.out.println("所有菜品已备齐,骑手取餐并开始配送!");} catch (InterruptedException e) {e.printStackTrace();}});// 启动所有线程chefA.start();chefB.start();chefC.start();rider.start();}
}
厨师A开始做宫保鸡丁...
厨师B开始做鱼香肉丝...
厨师C开始做麻婆豆腐...
骑手已到达餐厅,等待所有菜品完成...
厨师C:麻婆豆腐做好了!
厨师B:鱼香肉丝做好了!
厨师A:宫保鸡丁做好了!
所有菜品已备齐,骑手取餐并开始配送!

CyclicBarrier(循环屏障)

核心作用:让一组线程到达某个 “屏障点” 后互相等待,直到所有线程都到达屏障点,再一起继续执行后续操作

  • 基于 “等待计数” 实现:初始化时指定参与的线程数量( parties )。
  • 每个线程到达屏障点时,调用 await() 方法阻塞,直到最后一个线程到达,所有线程被同时唤醒。
  • 可重复使用:所有线程通过屏障后,计数会重置,可再次用于协调同一组线程。

特点

  • 线程之间是 “互相等待”(而非单方面等待)。
  • 支持在所有线程到达屏障后,自动执行一个预先设置的 Runnable 任务(如汇总结果)。
  • 适用于 “多线程分阶段协同工作” 场景(如多个线程先各自处理数据,全部完成后再一起进入下一阶段)。
image-20251006220435288

场景示例

3 名玩家各自从服务器拉取并加载资源,加载完成后互相等待,全部就绪后共同进入游戏地图

  1. 玩家 1~3(3 个线程):各自从本地加载地图、模型、音效等资源(耗时不同,比如玩家 1 需 10 秒,玩家 2 需 15 秒, etc.)。每个玩家加载完成后,会显示 “已就绪” 并等待其他人(调用 barrier.await())。
  2. 游戏屏障CyclicBarrier):初始化时设定 “需要 3 个玩家到达”(new CyclicBarrier(3, 游戏开始动作))。当最后 1 名玩家加载完成并调用 await() 后,屏障打开。
  3. 共同动作:所有玩家被同时唤醒,屏幕显示 “所有玩家加载完成,游戏开始!”,一起进入游戏地图。

代码生成

import java.util.concurrent.CyclicBarrier;public class GameLoadingDemo {public static void main(String[] args) {// 初始化 CyclicBarrier:需要3个线程到达屏障,之后执行“共同进入地图”的动作CyclicBarrier barrier = new CyclicBarrier(3, () -> {System.out.println("所有玩家加载完成,一起进入游戏地图!");});// 玩家1:加载耗时10秒Thread player1 = new Thread(() -> {try {System.out.println("玩家1 开始从服务器拉取并加载地图、模型、音效等资源...");Thread.sleep(10000); // 模拟10秒加载过程System.out.println("玩家1 加载完成,等待其他玩家...");barrier.await(); // 到达屏障,等待所有玩家就绪System.out.println("玩家1 进入游戏地图");} catch (Exception e) {e.printStackTrace();}}, "玩家1");// 玩家2:加载耗时15秒Thread player2 = new Thread(() -> {try {System.out.println("玩家2 开始从服务器拉取并加载地图、模型、音效等资源...");Thread.sleep(15000); // 模拟15秒加载过程System.out.println("玩家2 加载完成,等待其他玩家...");barrier.await(); // 到达屏障,等待所有玩家就绪System.out.println("玩家2 进入游戏地图");} catch (Exception e) {e.printStackTrace();}}, "玩家2");// 玩家3:加载耗时20秒Thread player3 = new Thread(() -> {try {System.out.println("玩家3 开始从服务器拉取并加载地图、模型、音效等资源...");Thread.sleep(20000); // 模拟20秒加载过程System.out.println("玩家3 加载完成,等待其他玩家...");barrier.await(); // 到达屏障,等待所有玩家就绪System.out.println("玩家3 进入游戏地图");} catch (Exception e) {e.printStackTrace();}}, "玩家3");// 启动3个玩家的加载线程player1.start();player2.start();player3.start();}
}
玩家1 开始从服务器拉取并加载地图、模型、音效等资源...
玩家2 开始从服务器拉取并加载地图、模型、音效等资源...
玩家3 开始从服务器拉取并加载地图、模型、音效等资源...// 10秒后
玩家1 加载完成,等待其他玩家...// 15秒后
玩家2 加载完成,等待其他玩家...// 20秒后
玩家3 加载完成,等待其他玩家...
所有玩家加载完成,一起进入游戏地图!
玩家1 进入游戏地图
玩家2 进入游戏地图
玩家3 进入游戏地图

Semaphore(信号量)

核心作用控制同时访问某个资源(或执行某个操作)的线程数量,本质是 “许可管理”。

  • 基于 “许可数” 实现:初始化时指定许可数量(允许的最大并发数)。
  • 线程需要访问资源时,调用 acquire() 申请许可(若许可不足则阻塞);访问完成后,调用 release() 释放许可(供其他线程使用)。

特点

  • 许可数可动态调整(通过 release(n) 增加许可,acquire(n) 一次性获取多个许可)。
  • 适用于 “限流” 或 “资源池控制” 场景(如控制数据库连接数、并发请求数)。

image-20251006223401185

场景示例

数据库只有 3 个连接(有限资源)Semaphore sem = new Semaphore(3) 初始化了 3 个 “许可”,表示最多同时有 3 个线程能拿到连接

  • 客户端 1、2、3 调用 sem.acquire() 时,能成功拿到许可,直接访问数据库;使用完毕后调用 sem.release() 释放许可。
  • 客户端 4、5 调用 sem.acquire() 时,因 3 个许可已被占满,会阻塞等待,直到有客户端释放许可后,才能拿到连接。

代码表示

import java.util.concurrent.Semaphore;public class DBConnectionPool {public static void main(String[] args) {// 初始化信号量:最多允许3个线程同时获取数据库连接(3个许可)Semaphore connectionSemaphore = new Semaphore(3);// 模拟5个客户端线程尝试访问数据库for (int i = 1; i <= 5; i++) {final int clientId = i;new Thread(() -> {try {System.out.println("客户端" + clientId + " 尝试获取数据库连接...");// 申请连接(获取许可):若已达3个连接,会阻塞等待connectionSemaphore.acquire();System.out.println("客户端" + clientId + " 成功获取连接,开始执行SQL...");// 模拟数据库操作耗时(1-3秒)Thread.sleep((long) (Math.random() * 2000 + 1000));} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放连接(归还许可)connectionSemaphore.release();System.out.println("客户端" + clientId + " 释放连接,当前可用连接数+1");}}).start();}}
}
客户端1 尝试获取数据库连接...
客户端2 尝试获取数据库连接...
客户端3 尝试获取数据库连接...
客户端4 尝试获取数据库连接...
客户端5 尝试获取数据库连接...
客户端1 成功获取连接,开始执行SQL...
客户端2 成功获取连接,开始执行SQL...
客户端3 成功获取连接,开始执行SQL...
客户端2 释放连接,当前可用连接数+1
客户端4 成功获取连接,开始执行SQL...
客户端1 释放连接,当前可用连接数+1
客户端5 成功获取连接,开始执行SQL...
客户端3 释放连接,当前可用连接数+1
客户端4 释放连接,当前可用连接数+1
客户端5 释放连接,当前可用连接数+1
http://www.dtcms.com/a/450743.html

相关文章:

  • 《工业边缘网关进阶指南:智慧工厂设备互联中的协议适配与数据预处理》
  • 十大免费文案网站口碑营销的模式
  • 个人免费设计网站活动策划案模板
  • 免费网站推广产品vue做的个人网站
  • 玉溪网站制作网站二级目录做优化
  • 白天/夜间野生动物检测识别数据集:近1w图像,5类,yolo标注
  • 山东省南水北调建设管理局网站网站空间控制
  • 温州网站制作价格做移动网站多少钱
  • 【LaTeX】 12 LaTeX 参考文献管理
  • 【郑州网站建设】网站群建设方案
  • 整站seo哪家服务好WordPress音乐主题模版 Musik
  • P5490 【模板】扫描线 矩形面积并
  • 网站皮肤样板如何打开网页
  • 电子商务网站建设 教学大纲中装建设市值
  • 做企业门户网站都免费建站平台哪个稳定
  • 网页设计的网站wordpress调用描述
  • 最新文生图模型进展:从Stable Diffusion 3到Sora的视觉革命
  • wap网站还用吗wordpress响应式主题
  • 江苏电商网站开发昆明网站搭建网站运营
  • 自动生成图片的网站商城模板网站模板
  • 湛江市微信网站建设企业中国互联网域名注册服务机构
  • 出国做博后关注哪些网站新冠北京最新消息
  • 做时尚网站的目的网站设计方式
  • 腾讯云建网站pc端网站未来
  • [Dify] 构建“公司内部制度”问答机器人:从知识导入到上线实战指南
  • 专业网站建站费用郴州市官网
  • PID--积分项I
  • 万维网网站服务的名称做网站需要注册什么公司
  • 相亲网站拉人做基金公司网站建设精品
  • 怎样做网站静态wordpress评论qq头像