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

CyclicBarrier、Semaphore、CountDownLatch的区别,适用场景

CyclicBarrierSemaphoreCountDownLatch 是 Java 并发包中用于线程协作的工具类,它们虽然都与线程同步相关,但设计目的和使用场景有显著差异。以下是它们的核心区别和典型应用场景:

1. CountDownLatch

核心机制
  • 一次性计数器:初始化时指定一个固定数值(count),线程调用 countDown() 减少计数器,其他线程通过 await() 等待计数器归零。
  • 不可重置:计数器归零后无法重复使用。
适用场景
  • 主线程等待子线程完成初始化:例如主线程等待所有服务启动后再处理请求。
  • 并行任务完成后汇总结果:多个子任务并行执行,主线程等待所有子任务完成后再汇总。
  • 模拟并发测试:通过 CountDownLatch 让所有线程同时开始执行。
特点
  • 一次性使用:计数器归零后不可重置。
  • 无回调机制,仅用于同步等待。
示例
CountDownLatch latch = new CountDownLatch(3);

// 子线程完成任务后调用 countDown()
executor.submit(() -> {
    doTask();
    latch.countDown();
});

// 主线程等待所有子线程完成
latch.await();

2. CyclicBarrier

核心机制
  • 可重复使用的屏障:一组线程相互等待,直到所有线程到达屏障点后,再一起继续执行。
  • 支持回调:可以指定一个 Runnable 任务,在所有线程到达屏障后触发。
适用场景
  • 多阶段任务协作:例如并行计算需要分阶段处理,每个阶段需等待所有线程完成。
  • 数据分批处理:多个线程处理数据后,在屏障点合并结果。
  • 模拟复杂并发逻辑:如多玩家游戏的回合制同步。
特点
  • 可重用:通过 reset() 方法重置计数器。
  • 支持屏障后回调函数,用于统一处理阶段结果。
示例
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("所有线程到达屏障点");
});

executor.submit(() -> {
    doPhase1();
    barrier.await(); // 等待其他线程
    doPhase2();
});

3. Semaphore

核心机制
  • 资源访问控制:通过“许可证”机制限制同时访问共享资源的线程数。
  • 支持公平/非公平模式:防止线程饥饿。
适用场景
  • 资源池管理:如数据库连接池、线程池。
  • 限流:控制接口的最大并发请求数。
  • 互斥锁扩展:通过 Semaphore(1) 实现类似锁的功能(但更灵活,可跨方法释放)。
特点
  • 动态调整:通过 acquire()release() 增减许可数。
  • 支持超时和中断响应,避免死锁。
示例
Semaphore semaphore = new Semaphore(5); // 允许5个线程同时访问

void accessResource() {
    semaphore.acquire(); // 获取许可
    try {
        useResource();
    } finally {
        semaphore.release(); // 释放许可
    }
}

关键区别总结

特性CountDownLatchCyclicBarrierSemaphore
重置能力一次性,不可重置可重复使用可重复使用
核心目的主线程等待子线程完成特定操作线程相互等待到屏障点控制资源访问的并发数
计数器方向递减(countDown()递增(await()获取/释放许可证(acquire()/release()
协作关系主线程等待子线程线程间相互等待线程与资源之间的协调
是否支持回调是(到达屏障后触发任务)
典型场景主从线程同步分阶段并行任务协同限流、资源池管理

如何选择?

  • 线程组协同(多阶段)CyclicBarrier
  • 主线程等待子线程完成CountDownLatch
  • 控制并发访问量或资源池Semaphore
  • 需重用或动态调整计数器CyclicBarrier 或 Semaphore
http://www.dtcms.com/a/109831.html

相关文章:

  • Vue3 Pinia Store使用示例
  • Linux 系统管理综合实训 —— 基于 NAT 模式的多 IP 配置、Nginx 服务部署及存储管理
  • 一周学会Pandas2 Python数据处理与分析-安装Pandas库
  • 在Vue3中格式化后端返回的Java Date类型数据为指定格式
  • 蓝桥杯真题———k倍区间
  • Android开发okhttp添加头部参数
  • 智能建造新范式:装配式建筑 4.0 的数字化进阶
  • SpringBoot集成Redis 灵活使用 TypedTuple 和 DefaultTypedTuple 实现 Redis ZSet 的复杂操作
  • Vue3 性能优化指南:从理论到实战
  • N皇后问题(dfs回溯)
  • 如何把网页文章转为pdf保存
  • 计算机网络基础:容灾备份与业务连续性保障
  • 在 Ubuntu 上离线安装 Prometheus 和 Grafana
  • GMS测试环境搭建二——aapt2报错
  • Kafka配置内外网访问(解决kafka外网访问broker超时)
  • Pytorch中预置数据集的加载方式
  • 斜方肌科学训练原则:上斜方肌多牵拉放松,中下斜方肌多锻炼强健。 | 告别圆肩驼背、“富贵包”
  • 第十四届蓝桥杯大赛软件赛省赛Python 研究生组:4.互质数的个数
  • Python星球日记 - 第2天:数据类型与变量
  • Android U 分屏——分割线相关
  • 基于ANSYS 概率设计和APDL编程的结构可靠性设计分析
  • mqtt封装与使用
  • 大模型面试题
  • SSL/TLS
  • 【系统架构设计师】系统架构评估中的重要概念
  • 几何法证明卡特兰数_栈混洗
  • 代码随想录|动态规划|21组合总和IV
  • 从零开始:使用Spring Boot和MyBatis实现CRUD操作全攻略
  • 25.Reactor
  • PHP代码审计-01