微服务 第二章 CountDownLatch和Semaphone的应用

本文主要探讨Java并发编程中的CountDownLatch和Semaphore工具类。CountDownLatch用于等待所有线程执行完毕,Semaphore则用于控制同时访问特定资源的线程数量。文中列举了各自的应用场景及实例代码,帮助理解其工作原理。

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

系列文章目录

第二章 CountDownLatch和Semaphone的应用
第一章 Java线程池技术应用

在这里插入图片描述



前言

Java JUI之并发编程,CountDownLatch和Semaphone的应用

1、CountDownLatch

CountDownLatch是一个同步工具类,它通过一个计数器来实现的,初始值为线程的数量。每当一个线程完成了自己的任务,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已执行完毕,然后在等待的线程就可以恢复执行任务。
CountDownLatch(int count):count为计数器的初始值(一般需要多少个线程执行,count就设为几)。

  • CountDownLatch(int count):cou
<think>好的,我现在需要回答用户关于Java中CountDownLatch的使用示例应用场景的问题。首先,我应该回忆一下CountDownLatch的基本概念作用。CountDownLatch是Java并发包中的一个同步工具类,主要用于让一个或多个线程等待其他线程完成操作后再继续执行。核心是通过一个计数器来实现,初始值设置为需要等待的线程数量,每个线程完成任务后调用countDown()方法将计数器减1,而等待的线程则调用await()方法阻塞直到计数器归零。 接下来,我需要整理用户提供的引用内容,从中提取有用的信息。根据引用[4][5],常见的应用场景包括应用启动时的初始化、并行任务的同步、测试高并发场景等。比如,主线程等待所有子线程完成初始化任务后再继续,或者多个线程同时开始执行任务以测试系统性能。此外,引用[5]还提到在数据拼接或复杂计算后汇总结果时使用CountDownLatch。 关于实现方式,引用[5]指出需要创建CountDownLatch实例,指定初始计数器值。工作线程完成任务后调用countDown(),而主线程调用await()等待。需要注意的是,countDown()应在finally块中调用,避免因异常导致计数器无法减到零,从而死锁。 接下来,我需要构造一个简单的使用示例。例如,主线程等待三个子线程完成任务。代码部分需要展示如何初始化CountDownLatch,如何在子线程中调用countDown(),以及主线程如何调用await()。同时,需要确保示例代码正确无误,符合Java语法规范。 然后,思考用户可能的相关问题,比如CountDownLatchCyclicBarrier的区别,如何避免死锁,或者适用场景的更多例子。这些问题有助于用户更深入理解工具的使用注意事项。 最后,检查回答是否符合用户的要求:结构清晰,分点说明应用场景,提供代码示例,并生成相关问题。确保引用的内容正确标注,如引用[4][5]的信息在适当的位置添加引用标识。</think>### Java CountDownLatch 应用场景及实现方式 #### 一、应用场景 1. **应用启动初始化** 等待多个初始化任务(如数据库连接、配置加载)完成后,再允许主线程处理请求[^4][^5]。 *示例*:主线程需等待日志服务、缓存系统、配置文件加载完成后再启动。 2. **并行任务同步** 主线程需等待多个子线程完成特定操作后才能继续。例如数据汇总或分布式计算结果的合并[^4]。 3. **高并发测试** 控制多个线程同时启动,模拟高并发场景。例如测试系统在瞬时高流量下的稳定性。 4. **任务分阶段执行** 确保前序阶段全部完成后再进入下一阶段。例如电商系统中订单创建、库存扣减、支付操作需按顺序执行。 --- #### 二、实现方式及示例代码 **核心方法**: - `CountDownLatch(int count)`:构造函数,设置初始计数器 - `countDown()`:计数器减1(子线程调用) - `await()`:阻塞等待计数器归零(主线程调用) **示例:主线程等待3个子线程完成任务** ```java public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { final int THREAD_COUNT = 3; CountDownLatch latch = new CountDownLatch(THREAD_COUNT); for (int i = 1; i <= THREAD_COUNT; i++) { new Thread(() -> { try { System.out.println(Thread.currentThread().getName() + " 开始执行任务"); Thread.sleep((long)(Math.random() * 2000)); System.out.println(Thread.currentThread().getName() + " 任务完成"); } catch (InterruptedException e) { e.printStackTrace(); } finally { latch.countDown(); // 确保异常时仍会减计数 } }, "工作线程-" + i).start(); } System.out.println("主线程等待所有子任务完成..."); latch.await(); // 阻塞直到计数器归零 System.out.println("所有任务已完成,开始汇总结果"); } } ``` **输出可能**: ``` 主线程等待所有子任务完成... 工作线程-1 开始执行任务 工作线程-2 开始执行任务 工作线程-3 开始执行任务 工作线程-1 任务完成 工作线程-3 任务完成 工作线程-2 任务完成 所有任务已完成,开始汇总结果 ``` --- #### 三、注意事项 1. **避免死锁** - 始终在`finally`块中调用`countDown()`,防止异常导致计数器未归零[^5] - 初始计数器必须与实际任务数量一致 2. **不可重用** CountDownLatch计数器归零后不可重置,如需重用应选择`CyclicBarrier` 3. **性能影响** `await()`会阻塞线程,长时间等待需设置超时参数:`await(long timeout, TimeUnit unit)` ---
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青花锁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值