并发 同步器CyclicBarrier(循环栅栏)、CountDownLatch(闭锁)、Semaphore(信号灯)---简单学习

本文介绍了Java并发编程中常用的三种工具类:CyclicBarrier、CountDownLatch和Semaphore。详细解释了它们的作用、使用方法及应用场景,帮助读者更好地理解这些工具在多线程环境下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CyclicBarrier:
  • java.util.concurrent.CyclicBarrier包下提供的一个同步器类,该类会等待指定个数的线程全部执行完后才执行后续逻辑。

该类提供了两个构造函数:

注:译自java api

CyclicBarrier(int parties)
创建一个新的循环栅栏,当给定的缔约方(线程)等待它时,它将会等待,并且当栅栏被等待时,它不会执行预先定义的操作

CyclicBarrier(int parties, Runnable barrierAction)

创建一个新的循环栅栏,当给定的缔约方(线程)等待它时,它将会等待,当障碍被触发时,它将执行给定的barrier动作,由最后一个进入屏障的线程执行

注:译自java api

intawait()
等待直到所有各方都在这个障碍上等待。
int

await(long timeout, TimeUnit unit)

等待直到所有各方都在这个障碍上等待,或者指定的等待时间流逝。

intgetNumberWaiting()
返回目前在隔离墙等候的缔约方的数量
intgetParties()
返回到达此障碍所需的缔约方数量
booleanisBroken()
如果这个障碍处于一个破碎的状态。
void

reset()

将障碍重新设置为初始状态。

实例:



使用ArrayList会造成线程安全问题图解:

两个对象或多个,同时都拿到了空的ArrayList


使用线程安全vector,保证每次操作集合的都只是一个线程在进行,或者使用lock进行加锁:


这里使用了并发包下的ExecutorService,在执行完毕后应当关闭线程

二、CountDownLatch(闭锁)  

       其内部维护了一个计数器,每个线程结束后对计数器值进行减一,当count为0时表示所有线程执行完成才执行下一步操作。

CountDownLatch(int count)

构造一个用给定计数初始化的闭锁。

提供方法:

注:译自java api

voidawait()
使当前线程等待直到门闩数到零为止,除非线程被中断。
booleanawait(long timeout, TimeUnit unit)
使当前线程等待直到门闩数到零为止,除非线程被中断,否则指定的等待时间就会流逝。
voidcountDown()
如果计数达到零,就会释放锁的计数,释放所有等待的线程。
longgetCount()
返回当前计数。
StringtoString()
返回一个识别这个锁的字符串,以及它的状态。

await():该方法会在检查是否所有线程执行完毕,且cout值是否为0

实例:


多线程业务逻辑:



三、Semaphore(信号灯):

   该类内部维护了一个'许可证',多线程下执行每个线程都会去拿一个许可证,执行结束后释放许可证,若有许可证,并立即返回,将可获得的许可证数量减少一个。如果没有许可证可用,那么当前线程就会因线程调度的目的而被禁用,并且处于休眠状态。适用场景-多个对象轮番操作少于多个对象内容-如:3台机器7个工人轮番使用。

实例:


获取许可证和释放许可证:


结果:


若未进行release()释放许可证,则会出现未获得许可证的线程会一直等待并尝试获得许可证。

<think>好的,我现在需要回答用户关于Java并发工具的问题,包括SemaphoreCountDownLatchCyclicBarrier、Phaser和Exchanger的使用场景及区别。首先,我需要回忆这些工具的基本概念和功能,然后根据提供的引用资料来整理它们的区别和适用场景。 首先,Semaphore是一个信号量,主要用于控制同时访问特定资源的线程数量,比如限流。引用[2]和[5]提到,Semaphore通过许可证机制来管理资源,线程需要获取许可证才能执行,使用完后释放。这在数据库连接池或限流场景中很常见。 接下来是CountDownLatch,这是一个倒计时门闩,允许一个或多个线程等待其他线程完成操作。引用[2]和[4]指出,它的计数器只能使用一次,适用于一次性的等待,比如主线程等待所有子线程完成任务后再继续执行。 CyclicBarrier是循环屏障,和CountDownLatch类似,但可以重复使用。引用[3]和[4]提到,它让一组线程互相等待,直到所有线程到达屏障点,然后执行预设的动作。这在多线程分阶段处理数据时很有用,比如分批处理后的汇总操作。 Phaser在引用[4]和[5]中被提到,类似于CyclicBarrier,但支持动态调整参与的线程数。适用于更复杂的多阶段任务,比如游戏中的多个关卡,每个关卡需要不同数量的线程协同。 Exchanger用于两个线程间的数据交换,引用[4]说明它适合在两个线程处理不同实例数据时交换结果,比如生产者-消费者模式中的数据传递。 接下来需要整理它们的区别。可重复性方面,CountDownLatch不能重复使用,而CyclicBarrier和Phaser可以。作用对象上,CountDownLatch关注事件倒数,而CyclicBarrier和Phaser关注线程到达。Semaphore控制资源访问数量,Exchanger专注于线程间交换数据。 使用场景需要具体举例,比如Semaphore用于资源池,CountDownLatch用于启动前的等待,CyclicBarrier用于分批处理,Phaser用于多阶段任务,Exchanger用于线程间数据交换。 最后要确保回答结构清晰,分点说明每个工具的特点、使用方法和区别,并生成相关问题。需要参考提供的引用资料,正确引用相关内容,比如CyclicBarrier的可重复性来自引用[2]和[3],CountDownLatch的一次性使用来自引用[2]和[4]。</think>### Java并发工具对比解析 #### 一、工具特性与使用场景 1. **Semaphore(信号量)** - **作用**:控制同时访问特定资源的线程数量,实现限流/资源池管理[^2][^5]。 - **核心方法**:`acquire()`获取许可证、`release()`释放许可证。 - **示例**:数据库连接池(限制最大并发连接数)。 ```java Semaphore semaphore = new Semaphore(5); // 允许5个线程同时访问 semaphore.acquire(); // 获取许可证 semaphore.release(); // 释放许可证 ``` 2. **CountDownLatch(倒计时门闩)** - **作用**:让主线程等待一组子线程完成任务(一次性)[^2][^4]。 - **核心方法**:`countDown()`减少计数、`await()`等待计数归零。 - **示例**:启动服务时等待所有组件初始化完成。 ```java CountDownLatch latch = new CountDownLatch(3); latch.countDown(); // 子线程完成任务后调用 latch.await(); // 主线程阻塞直到计数为0 ``` 3. **CyclicBarrier(循环屏障)** - **作用**:让一组线程互相等待,到达屏障后执行预设动作(可重复使用)[^3][^4]。 - **核心方法**:`await()`触发等待。 - **示例**:多线程分批处理数据后汇总结果。 ```java CyclicBarrier barrier = new CyclicBarrier(5, () -> System.out.println("所有线程就绪")); barrier.await(); // 线程到达屏障后等待 ``` 4. **Phaser(阶段器)** - **作用**:支持动态调整线程数量的多阶段协同(复杂版CyclicBarrier)[^4][^5]。 - **核心方法**:`arriveAndAwaitAdvance()`进入下一阶段。 - **示例**:游戏关卡加载(不同关卡需不同数量的线程协同)。 5. **Exchanger(交换器)** - **作用**:两个线程在特定点交换数据[^4]。 - **核心方法**:`exchange()`提交数据并等待对方线程。 - **示例**:生产者-消费者模式中缓冲区交换。 ```java Exchanger<String> exchanger = new Exchanger<>(); String data = exchanger.exchange("数据A"); // 线程A发送并接收线程B的数据 ``` --- #### 二、核心区别总结 | **维度** | **CountDownLatch** | **CyclicBarrier** | **Semaphore** | **Phaser** | **Exchanger** | |-----------------|--------------------------|--------------------------|-------------------|---------------------|--------------------| | **可重复性** | 一次性 | 循环使用 | 许可证可重复获取 | 多阶段动态调整 | 单次数据交换 | | **核心目标** | 等待事件完成 | 线程组同步 | 控制资源并发量 | 分阶段协同 | 线程间数据交换 | | **触发动作** | 无 | 支持`barrierAction` | 无 | 按阶段自定义逻辑 | 无 | | **参与者数量** | 固定(初始化时设定) | 固定(初始化时设定) | 动态(许可证数量)| 动态(可注册/注销) | 仅两个线程 | --- #### 三、典型应用场景对比 1. **CountDownLatch**:主线程等待微服务启动完成[^2]。 2. **CyclicBarrier**:并行计算中多线程分片处理数据后汇总[^3]。 3. **Semaphore**:限制文件下载的并发线程数[^5]。 4. **Phaser**:多阶段任务(如分布式任务分片-合并-写入)[^4]。 5. **Exchanger**:双缓冲区数据交换(生产者-消费者高效协作)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值