Java多线程同步工具类CountDownLatch详解
简介
CountDownLatch
是一个多线程同步工具类,在多线程环境中它允许多个线程处于等待状态,直到前面的线程执行结束。从类名上看CountDown
既是数量递减的意思,我们可以把它理解为计数器。
核心方法
countDown()
:计数器递减方法。await()
:使调用此方法的线程进入等待状态,直到计数器计数为0时主线程才会被唤醒。await(long, TimeUnit)
:在await()
方法的基础上增加了超时策略,若等待超时仍未有结果则会直接唤醒主线程运行。
CountDownLatch如何使用
在这里我们用一段简单的代码进行演示:
@Slf4j public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); new Thread(() -> { log.info("hello this is thread one"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread two"); countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread three"); countDownLatch.countDown(); }).start(); countDownLatch.await(); log.info("say good bye!"); } }
由上面的代码可见,我们创建了一个CountDownLatch
计数器为3和三个线程同步运行。在main主线程中调用了countDownLatch.await()
方法使主线程进入阻塞。其中三个线程任务执行完毕后都会调用countDownLatch.countDown()
方法对计数器进行递减,当三个线程任务都执行完毕后计数器计数值为0时主线程被唤醒。
注:在创建
CountDownLatch
实例时必须定义计数器值,一般相对较合理的用法是该值的定义需要经过合理的计算使计数值与需要并行的线程数相等,在每个线程执行完成后做计数递减,最终唤醒主线程继续执行。
CountDownLatch
计数值设置大于线程数,那么最终所有线程都执行完了,而计数为递减到0那么主线程将会一直处于等待状态。CountDownLatch
计数值设置小于并发线程数,那么可能在部分线程未执行完毕时,计数就已经递减到0,则主线程会被提前唤醒。
CountDownLatch运行流程
如下图,主线程阻塞与唤醒的核心就是计数器,只有当所有线程执行完成计数逐个递减最终才会唤起await()
阻塞中的主线程。
注:
await()
可以阻塞一个线程,也可以阻塞多个线程,如果是阻塞多个线程,那么在计数为0时将会唤醒所有被阻塞的线程。
运用场景
在简单了解完CountDownLatch
的作用后,相信各位最终目的还是想了解如何去使用,在哪些场景下使用更加合适,接下来我就拿一个对账业务的场景详细分析一下。
相信现在很多平台都会对接银联、微信、支付宝等支付渠道做交易,那么在这样的场景下对账是不可避免的。对账通常都会在每日的凌晨去处理,一方面是凌晨时间点多数平台访问量都会较小,服务器压力也比较轻松,而且此时出账也比较合理,所以在这个时间点做对账也是一个大数据量计算的操作。
上面讲这么多好像都没说到重点,在处理对账之前首先我们肯定是需要通过各个支付渠道获取对账单文件,那么该如何操作呢?
- 对账文件下载(第一阶段):在这种情况下可以设计三个任务并发去获取对账文件,使用
CountDownLatch
阻塞主线程,等待三个任务都获取到文件的时候做计数递减,最终唤醒主线将标记本阶段处理完成,并发起进入下一阶段的通知。 - 对账文件解析(第二阶段):在上个阶段已下载完成的文件文件中,此阶段要做的就是解析文件。由于三个渠道都是不同的厂家那么文件的内容格式肯定都是不一样的,这时候我们又可以使用
CountDownLatch
启动三个线程分别去解析各自的对账文件,最终将文件内容转换为业务所需的数据统一格式入库,在三个任务都入库完成后主线程又被唤醒标记完成后,通知下一阶段开始进入工作。 - 对账结算(第三阶段):在上一阶段的数据入库完成后,此阶段要做的就是比对每一笔交易是否准确,一般都是按单号与交易渠道比对交易的金额是否一致,如果金额一致则该笔交易结算成功,否则将交易判定为异常交易,并入库处理。由上面的流程分析我们就可以设计相对合理的
CountDownLatch
计数,结合Semaphore
信号量控制并发量同时对对比交易单做并发处理,最终带所有交易单处理完成后唤醒主线程标记对账完成,并通知下一阶段进行出账。 - 出账(第四阶段):通常平台在对账完成后会进行出账,也就是按照平台的业务规则出具相关的账单方便财务人员进行统计。
总结
多线程并发的情况下需要做好同步处理,结合CountDownLatch
充分的运用到业务场景当中还是挺有必要的,凡是需要在多个任务执行完成后再去做另一件事的情况都可以考虑使用CountDownLatch
,合理使用但请不要滥用,特别上面也提到过计数值需要确定,否则可能导致多任务无法做到同步甚至造成主线程无限等待。
到此这篇关于Java多线程同步工具类CountDownLatch详解的文章就介绍到这了,更多相关Java CountDownLatch内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://juejin.cn/post/7112820343252713480
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
C# WinForm多线程解决界面卡死问题的完美解决方案,使用BeginInvoke
问题描述:当我们的界面需要在程序运行中不断更新数据时,当一个textbox的数据需要变化时,为了让程序执行中不出现界面卡死的现像,最好的方法就是多线程来解决一个主线程来创建界...2020-06-24java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要介绍了c# 多线程处理多个数据的方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-03-31
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
Elasticsearch工具cerebro的安装与使用教程
这篇文章主要介绍了Elasticsearch工具cerebro的安装与使用教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-08- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了C#基于委托实现多线程之间操作的方法,实例分析了C#的委托机制与多线程交互操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
- 这篇文章主要介绍了C#多线程中的异常处理操作,涉及C#多线程及异常的捕获、处理等相关操作技巧,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了c# 线程同步的相关资料,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...2020-08-29