三个好用的并发工具类

转载自  三个好用的并发工具类

以前的文章中,我们介绍了太多的底层原理技术以及新概念,本篇我们轻松点,了解下 Java 并发包下、基于这些底层原理的三个框架工具类。

它们分别是:

  • 信号量 Semaphore

  • 倒计时门栓 CountDownLatch

  • 屏障 CyclicBarrier

所以,既然是工具类,那么必然是离不开特定的场景的,于是相互之间没有谁优谁劣,只有谁更合适。

 

信号量 Semaphore

Semaphore 适用于什么样的使用场景呢,我们举个通俗的例子:

假如现在有一个停车场,里面有只十个停车位,当着十个停车位都被占用了,外面的车就不允许进入了,就必须在外面等着。出来一辆车才允许进去一辆车

这个场景不同于我们一般的并发场景,一般来说,我们的临界资源只能允许一个线程进行访问,其他线程都地等着。

但是,有一种场景是,临界资源允许多个线程同时访问,超过限定数量的外的线程得阻塞等待。

这种情境使用原始的那一套也是能实现的,但那叫「造轮子」,Java 并发框架下给我们提供了一个工具类,专门适用这种场景。

Semaphore 可以说是为上述这种场景而生的一个工具类,我们写个 demo 实现上述逻辑:

执行程序之后,你会看到:

 

你看,出来一个线程才允许进去一个线程,这就是 Semaphore。

semaphore 的内部原理其实你去看源码,你会发现和我们的 ReentrantLock 的实现是极其类似的,包括公平与非公平策略的支持,只不过,AQS 里面的 state 在前者的实现中,一般小于等于一(除非重入锁),而后者的 state 则小于等于十,记录的是剩余可用临界资源数量。

所以,semaphore 天生就存在一个问题,如果某个线程重入了临界区,可用临界资源的数量是否需要减少?

停车场一共十个停车位,一辆车进去并占有了一个停车位,过了一段时间,这个向管理员报告,我还要占用一个停车位,先不管他占两个干啥,此时的管理员会同意吗?

实际上,在 Java 这个管理员看来,已经进入临界区的线程是「老爷」,提出的要求都会优先满足,即便他自身占有的资源并没有释放。

所以,在 Semaphore 机制里,一个线程进入临界区之后占用掉所有的临界资源都是可能的。

 

倒计时门栓 CountDownLatch

下面我们来看看这个 CountDownLatch,名字听起来挺高级,究竟提供了怎样的功能呢?

有这么一个常见的场景,我们一起来看看:

大家日常经常使用的拼多多,一件商品至少需要两到三人拼团,商家才会发货。

这里,我们不去研究它的商业模式,不管他是怎么实现盈利的,就这么一种场景,如果要用基本的并发 API 来实现,你可能会想到:

来一个线程阻塞一次,知道达到指定的数量后,全部唤醒

对,没错,CountDownLatch 内部就是这样实现的,轮子已经帮你造好了,我们来看看该怎么实现上述的模型案例:

多运行几次,你会发现结果不会错,拼团的人先后顺序可能不同,但商家一定是在三个人都准备好了之后才会发货。

除此之外,它还有更多的应用,比如百米赛跑,只有当所有运动员都准备好了之后,裁判员才会吹响哨子,等等等等。

实现原理也基本和显式锁类似,不同点依然在于对 state 的控制,CountDownLatch 只判断 state 是否等于零,不等于零就说明时机未到,阻塞当前线程。

而每一次的 countDown 方法调用都会减少一次倒计时资源,直至为零才唤醒阻塞的线程。

 

循环屏障 CyclicBarrier

CyclicBarrier 其实和 CountDownLatch 很像,我们先介绍完 CyclicBarrier,然后再和你一起去比较比较他俩的区别和相似点。

考虑这么一个场景:

公寓的班车总是在公寓楼下装满一车人之后,出发并开到地铁站,接着再回来接下一班人。

这么一个场景,我们考虑该怎么实现:

 

效果大概就是这个样子:

CyclicBarrier 就像一个屏障,实例化的时候需要传入两个参数,第一个参数指定我们的屏障最多拦截多少个线程后就打开屏障,第二个参数指明最后一个到达屏障的线程需要额外做的操作。

一般而言,最后一个线程到达屏障后,屏障将会打开,释放前面所有的线程,并在最后重新关上屏障。

CyclicBarrier 只需要用到一个 await 就可以完成所有的功能,我们总结下该方法的实现逻辑:

  1. 首先,减少一次可用资源数量

  2. 如果可用资源数为零,则说明自己是最后一个线程,于是会执行我们传入的额外操作,唤醒所有已经到达在等待的线程,并重新开启一个屏障计数。

  3. 否则说明自己不是最后一个线程,于是将自身线程在一个循环当中阻塞到一个条件队列上

好了,看完 CyclicBarrier 你会发现,它真的很类似我们的倒计时门栓,下面我们就来阐述他俩的区别与联系。

 

第一个区别

倒计时门栓 CountDownLatch 一旦被打开后就不能再次合上,也是说只要被调用了足够次数的 countDown,await 方法就会失效,它是一次性的。

CyclicBarrier 是循环发生的,当最后一个线程到达屏障,会优先重置屏障计数,屏障再次开启拦截阻隔。

 

第二个区别

CountDownLatch 是计数器, 线程来一个就记一个,此期间不阻塞线程,当达到指定数量之后才会去唤醒外部等待的线程,也就是说外部是有一个乃至多个线程等待一个条件满足之后才能继续执行,而这个条件就是满足一定数量的线程,这样才能激活当前外部线程的继续执行。

CyclicBarrier 像一个栅栏,来一个线程阻塞一个,直到阻塞了指定数量的线程后,一次性全部激活,让他们同时执行,像一个百米冲刺一样。

 

最后的最后

好了,以上就是我们 Java 并发包下面比较好用的三个工具类,其中前两个的底层实现几乎完全依赖显式锁的原理方法,后一个则是使用的显式锁加条件变量重新造的轮子,都是非常好用的工具!

除此之外还要说一点的是,整个并发这块内容,基本核心的东西我们都已经介绍完了,共计十四篇文章,从基本的线程概念,到锁原理,到线程池,再到异步任务,自认为总结的足够细致了,不知道你了解了多少呢?

记不住没关系,我也为你提供了一份思维导图的总结,罗列了上述基本的内容,你可以对照着进行回顾,同时也欢迎你私信我讨论探究。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Error Handling in ASP.NET Core

前言 在程序中,经常需要处理比如 404,500 ,502等错误,如果直接返回错误的调用堆栈的具体信息,显然大部分的用户看到是一脸懵逼的,你应该需要给用户返回那些看得懂的界面。比如,“当前页面不存在…

基于python的selenium

一.安装 安装WebDriver 查看chrome版本号,设置-帮助-关于Google chrome,找到版本号。 可以到这个网站进行下载对应版本的chromedriver,如果chrome浏览器版本过高,可以下载最新版的chromedriver进行使用 Chrome for Testing availability 下载下来之后…

多信息登录、检测用户信息是否完善且引导补全

大家好,我是雄雄,欢迎关注:穆雄雄的博客 前言 现在是2022年4月28日13:41:29! 今天分享两块内容。 1.需求:用户可以通过手机号、邮箱来注册我们的系统,用户完成之后,可以去完善自己的个人信息…

Ch4302-IntervalGCD【线段树,树状数组,GCD】

正题 题目链接:http://contest-hunter.org:83/contest/0x40%E3%80%8C%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E8%BF%9B%E9%98%B6%E3%80%8D%E4%BE%8B%E9%A2%98/4302%20Interval%20GCD 题目大意 要求支持区间修改和区间求gcd。 解题思路 如果直接线段树gcd的话,区间…

PNG 图片压缩原理解析

转载自 PNG 图片压缩原理解析 什么是PNG PNG的全称叫便携式网络图型(Portable Network Graphics)是目前最流行的网络传输和展示的图片格式,原因有如下几点: 无损压缩:PNG图片采取了基于LZ77派生算法对文件进行压缩&…

element ui实现多层级复杂表单的操作(添加与回显)之表单操作交互操作

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂 前言 现在是2022年5月3日11:47:15!劳动节假期已经过去了三天了,今天是被封家里的第7天,也是解封的第一天。 说实话,在家里的工作效率一点都…

POJ2182-Lost Cows【树状数组,二分】

正题 题目链接:http://poj.org/problem?id2182 题目大意 给出每头牛前面有多少个比它高的,求每头牛的最大高度。 解题思路 建立一个01序列,表示每个高度是否被占用过,然后倒序扫描每次找到一个没有被占用的第Ai1个位置,然后标…

TypeScript 2.5 发布,增加语言级重构

在 TypeScript 2.5 版本中,Microsoft 专注于提高开发人员的生产力,其范围已经超出了代码编辑器所提供的常见功能。 习惯于类型语言(如 C#)的开发人员喜欢使用那些可以轻松执行常见重构的工具。现在 TypeScript 可以利…

永远不要在 MySQL 中使用 UTF-8

转载自 永远不要在 MySQL 中使用 UTF-8 最近我遇到了一个 bug&#xff0c;我试着通过 Rails 在以“utf8”编码的 MariaDB 中保存一个 UTF-8 字符串&#xff0c;然后出现了一个离奇的错误&#xff1a; Incorrect string value: ‘\xF0\x9F\x98\x83 <…’ for column ‘sum…

element ui实现多层级复杂表单的操作(添加与回显)之添加功能实现

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月3日13:35:15&#xff01;文接上篇。[element ui实现多层级复杂表单的操作&#xff08;添加与回显&#xff09;之表单操作交互操作](element ui实现多层级复杂表单的操…

POJ1151-Atlantis【线段树,扫描线,离散化】

正题 题目链接:http://poj.org/problem?id1151 题目大意 有n个矩形&#xff0c;求所以矩形的覆盖面积。 解题思路 我们用离散化一个坐标&#xff0c;然后每次用线段树维护这个宽度内覆盖高度和&#xff0c;然后定义左上的点是加入&#xff0c;右下的点是弹出。 code #incl…

Entity Framework Core Like 查询揭秘

在Entity Framework Core 2.0中增加一个很酷的功能&#xff1a;EF.Functions.Like()&#xff0c;最终解析为SQL中的Like语句&#xff0c;以便于在 LINQ 查询中直接调用。 不过Entity Framework 中默认提供了StartsWith、Contains和EndsWith方法用于解决模糊查询&#xff0c;那…

JVM发生OOM的 8 种原因、及解决办法

转载自 JVM发生OOM的 8 种原因、及解决办法 1、Java 堆空间 发生频率&#xff1a;5颗星 造成原因 无法在 Java 堆中分配对象 吞吐量增加 应用程序无意中保存了对象引用&#xff0c;对象无法被 GC 回收 应用程序过度使用 finalizer。finalizer 对象不能被 GC 立刻回收。fina…

element ui实现多层级复杂表单的操作(添加与回显)之回显功能实现

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月3日17:02:30&#xff01;文接上两篇。 [element ui实现多层级复杂表单的操作&#xff08;添加与回显&#xff09;之表单操作交互操作](element ui实现多层级复杂表单…

在Mac的Docker中运行DotNetCore2.0

最近学习Angular4&#xff0c;服务端准备使用DotNetCore API来实现&#xff0c;本文简单介绍下在Mac中怎样将DotNetCore程序部署在Docker中&#xff0c;并使用Nginx做反向代理让程序可以跑起来。 具体步骤如下 安装Docker拉取DotNetCore镜像使用VS For Mac创建DotNetCore应用…

POJ2482-Stars in Your Window【线段树,扫描线,离散化】

正题 题目链接:http://poj.org/problem?id2482 题目大意 有若干个点&#xff0c;每个点有不同的权值&#xff0c;求用一个h*w的矩阵扩起来的权值最大。 解题思路 先离散化一个坐标&#xff0c;然后另一个坐标就在x∼xw−1x∼xw−1这个区域加上权值&#xff0c;然后每个点的…

20个高级Java面试题汇总

转载自 20个高级Java面试题汇总 译文链接&#xff1a;http://www.codeceo.com/article/20-java-advanced-interview-questions.html 英文原文&#xff1a;Advanced Java Interview Questions 翻译作者&#xff1a;码农网 – 小峰 这是一个高级Java面试系列题中的部分。这一部分…

springboot实现复杂业务下的更新操作

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月4日19:25:55&#xff01;今天写了个这样的功能&#xff1a; 某用户在一天内有多个训练项目&#xff0c;比如&#xff1a;晨跑&#xff0c;有氧训练&#xff0c;跳绳这…

HDOJ5542-The Battle of Chibi【树状数组,dp】

正题 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid5542 题目大意 求序列A有多少个长度为M的递增子序列。 解题思路 用fi,jfi,j表示长度为i&#xff0c;以AjAj结尾的序列的个数。然后显然得出动态转移方程通过上一次从任意一个地方转移&#xff0c;动态转移方程&…

ASP.NET Core中为指定类添加WebApi服务功能

POCO Controller是 ASP.NET Core 中的一个特性&#xff0c;虽然在2015年刚发布的时候就有这个特性了&#xff0c;可是大多数开发者都只是按原有的方式去写&#xff0c;而没有用到这个特性。其实&#xff0c;如果利用这个特性进行稍微封装后&#xff0c;用在SOA架构中Service层的…