从火箭发场景来学习Java多线程并发闭锁对象
从火箭发场景来学习Java多线程并发闭锁对象
倒计时器场景
在我们开发过程中,有时候会使用到倒计时计数器。最简单的是:int size = 5; 执行后,size—这种方式来实现。但是在多线程并发的情况下,这种操作会不安全的。举个现实中最典型的一个例子:火箭发射的案例。
大家都看过火箭发射的直播吧。火箭在发送的时候,有很多设备需要检查是否都准备就绪。在总控室得到所有设备都准备就绪后,才会下达发射的命令。我们也知道,火箭发射有很多设备需要检验,这不是一个部门一个一个检查的,而是多个部门协同配合实现的。如果把一个个部门看作不同的线程的话。我们就可以假设:
如果是一个部门一个一个设备检查,这就是单线程操作的;
如果是多个部门协同配合的话,就是多线程的。
所以说,在火箭发射前检查设备是 多线程情况下进行的。
我们也不知道,不同部门负责检查的设备的复杂度不同,速度不同,就会导致有些部门检查完成的快,有些部门检查完成的慢。这个过程我们可以理解为不同线程在竞争CPU资源的时候不同。
假设有5个部门同时协同工作,这5个部门的操作可以看作是一组操作。因为速度不同,那么总控室下达发射的命令是以哪个检查完毕为准呢?是A部门还是B部门或者D部门呢?都不是,总控室下达发射的命令是在得到5个部门都检查完毕后才会下达发射的命令。我们也可以理解为总控室在得到这一组(五个部门)都操作完成才执行的。此时总控室可以理解为一个线程,五个部门一组可以理解一个线程组。
从上面现实生活中的案例分析,我们来想想上面的操作用Java程序怎么实现 ?
使用count—的代码实现
模拟不同部门的线程:
我们先来看看常规的。使用count--的效果。
模拟总控室的主线程:
从上面代码中,我们可以看到当计数器count减到0的时候,总控室下达发射命令。这个从逻辑上来说,是正确的,没问题的。我们来看看运行结果:
运行结果:
从运行结果,我们可以看到,当总控室接收到count =0的指令后,认为各个部门都已经检查完毕了。所以就下达了发射命令。但是在最后,我们发现火箭已经发射了,部门4和5才向总控室汇报检查完毕,准备就绪。这种情况是很危险的。因为我们知道火箭的造价是很昂贵的而且凝聚了很多科研人员的心血。如果因为某个部门未检查完毕就发射而导致火箭发射失败或者坠落,在现实生活中,这种情况是不允许出现的。
那么这种情况,在Java中,怎么解决呢?可以使用countdownlatch这个对象来解决。
Countdownlatch
Countdownlatch是什么?
先来看看源码中怎么解释的:A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
什么意思呢?
简单的来说,是一个同步辅助工具类,运行一个或多个线程在等待其他线程完成一组操作后再接着执行的工具类。
实现的流程:
通过一个计数器来实现的,计数器的初始值就是要执行的线程的数量。每当一个线程执行完毕之后,计数器的值就会减一,当计数器的值减少到0的时候,表示所有的线程都执行完毕了。然后再闭锁上等待的其他线程就可以恢复正常工作了。
来看看主要的方法
说明:
Sync:是countdownlatch内部类,继承AbstractQueuedSynchronizer使用AQS状态来代替计数的。
有参构造器:public CountDownLatch(int count){}
await():等待方法。还有一个带参数重载的方法。
countdown():执行计数器减1操作的方法。
使用countdownlatch模拟火箭发射前准备代码:
我们来看看使用countdownlatch来模拟火箭发射前准备会不会出问题。
来看看模拟部门的线程代码:
为了保证计数器减一操作不受子线程运行结果影响,讲count.coundDown()操作放在finally代码块里面。
再来看看总控室下达发射命令的主线程:
在downLatch.await()之后,下达发射命令。
查看运行结果:
我们可以看到,当所有部门都准备就绪后,总控室接收到完成的指令后,下达发射火箭命令。这个流程才是正常的。从运行结果来看也是正常的。
使用场景:
场景1:某线程在运行前需要等待其他N个线程执行完成之后在执行。
比如:
容器启动spring 容器的启动,需要初始化、bean装配、检查其他依赖等加载完毕之后,在主线程在继续执行;
在比如:电商中统计库存问题。我们知道,一个电商项目有很多分类,不同分类下的库存不一样。如果要统计当前剩余总库存。这个时候,就可以使用其他线程统计每个分类下的库存。等所有分类都统计完成之后,主线程在进行汇总操作。
关注凯哥:
个人博客:www.kaigejava.com
个人公众号:凯哥Java(kaigejava)
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
冠状病毒给美国带来的另项挑战:VPN使用量飙升150%!
随着冠状病毒的传播,许多公司要求员工在家工作,这给远程网络技术带来了意想不到的压力,并引起了网络负载和安全方面的担忧。(国内亦是如此,很多云盘都在扩容)。 在过去的几十年里,企业促进了远程工作者的快速增长,估计超过了400万人。由于新型冠状病毒在家办公人数激增,需要增加容量,与此同时,新用户也在线上办公的路上。 VPN供应商Atlas的研究显示,3月9日至15日期间,美国的VPN使用量增长了53%,而且增长速度可能更快。VPN在意大利的使用,那里的病毒爆发比美国早了大约两周,在过去一周增长了112%。 Atlas VPN的首席运营官瑞秋·韦尔奇(Rachel Welch)在一份声明中说:“我们估计,到本月底,美国的VPN使用量可能会增长150%以上。” 为了避免蜂窝数据网络的拥塞,美国联邦通信委员会(Federal Communications Commission)已经允许T-Mobile临时接入其他被许可方拥有的600MHz频段的频谱。 例如T-Mobile要求就是“让美国人更容易参与远程学习和远程工作,并实时保持联系。” 一些业内人士警告称,在依赖无线连接的地区,最后一英里的互联...
- 下一篇
Java并发编程学习前期知识上篇
Java并发编程学习前期知识上篇 我们先来看看几个大厂真实的面试题: 从上面几个真实的面试问题来看,我们可以看到大厂的面试都会问到并发相关的问题。所以 Java并发,这个无论是面试还是在工作中,并发都是会遇到的。Java并发包JUC(java.util.concurrent)有了解过哪些?并发包实现最重要的是什么?其原理是什么知道吗?何为JMM的可见性?volatiile关键字是怎么实现变量可见性的?如果想要学好并发,弄懂理解透彻的话,凯哥觉得以下计算机的知识还是要了解了解。本次《Java并发编程-前期准备知识》凯哥准备用两篇来介绍,主要包括以下内容:简单介绍内存之间可见性是什么?volatile关键字在Java语言规范中是怎么定义的?知道JVM但是你知道JMM是什么吗?计算机中CPU是怎么处理数据的?通过CPU处理数据来深刻理解线程之间可见性。还有就是volatile是怎么保证可见性的呢?其实现的两条原理是什么? Java并发包(JUC)下的类或者可以说Java并发机制的实现有一个关键字很重要:volatile。这个关键字,修饰的变量能够实现“可见性”。那么实现的原理是什么? 可见性...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- 设置Eclipse缩进为4个空格,增强代码规范
- Mario游戏-低调大师作品
- MySQL8.0.19开启GTID主从同步CentOS8
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果