Java多线程工具类之循环栅栏计数器

Java多线程下循环计数器

本文主要内容:CyclicBarrier(下文中凯哥就用cycBar来代替)定义介绍;举例说明;代码演示;从源码来看原理及总结;CyclicBarrier与CountDownLatch(下文就用CountDown来代替)比较。

本篇是《凯哥(凯哥Java:kagejava)并发编程学习》系列之《并发工具类》教程的第二篇:《Java多线程下循环计数器》。

Java多线程工具类之循环栅栏计数器

一:CyclicBarrier是什么

cycBar是什么呢?

来看看JDKAPI文档中是怎么介绍这个对象的A P 4 % : * 6 Q

Java多线程工具类之循环栅栏计数器

翻译后大概意思:允许一组线程全部等待彼此达到共同的屏障点的同步辅助。循环阻塞在涉及固定大小的线程方的程序中很有用,这g S ? ( D G些线程必须偶尔等待彼此。屏障被称为循环 ,因为它可以在等待的线程被释放之后重新s / V 8 s使用。

有没有这种感觉:S j B x *每个汉字都认识,但是放在一起就不知道什么意` 0 + : 8 *思了?对!没错,就是这种感觉~~~///(^v^)\\\\\\~~~。上面G Y i k [翻译简单` b b一句话就是:有个可以循环利用的集合点。作用就是让所有线程都到达这个集合点W ^ L k R后,才会q g N 0 7 _ %继续下一步行动。如果还是不理解,请看下下面- ] O 5 $ n ^ Z生活中的例子。

二:CyclicBarrier生活中例子理解

在生活中,如果我们跟团旅游的话,就更容易理解W P s J l G R了。假设一个团有7个人,旅游团安排的旅游路线是八达岭长城故宫这个路线的一日游。游玩时间是3小时。三个小时后, 统一都到八达岭的集合点:入口处。点名等人员都到齐后,发车到下一个景点。这种场景相信大家都遇到过吧。八达岭入口的集合点不仅仅这个旅游团可以使用,其他的旅游团都可以使用的。如果站在多线程并发场u 5 ? Q ! o景下来分析的话:旅游团中每个成员都是一个线程,入口集合点就是屏障(Barrier),每个成员都必须到达集合点(循环到达Cyclic)且人数和旅游团人数相等的时候,才能触发旅游车发车去下一个景点的线程B D h } J c

还有一个例子更容易理解:集齐七龙珠,召唤神龙。相信看过《七龙$ 2 b W J 0 r B [珠》的都知道这个吧。想要召唤神龙的触发点就是集齐七个龙珠。

通过上面案例,大家是不是更容易理解了] v V . ] h J k?下面凯哥(kaigejava)将通过代码实现集齐七龙珠召唤神龙的操作。

三:代码D k a _ m 7 h R a演示

需求:集齐七颗龙珠,召唤神龙。

3.1:未使用cW e L 7 u Z 0ycba; ] C n { W O Qrr的时候

使用七个线程,来8 o y g 9代替找龙珠的七个任务。每个线程在找龙珠的时候,耗时2s.就sleep。最后,七个线程执行完成之后,使用召唤神龙的线程来召唤神龙。a [ 5 J k代码如下图:

Java多线程工具类之循环栅栏计数器

运行结果:

Java多线程工具类之循环栅栏计数器

我们发现,龙珠还没有找到呢,神龙就出现了。这个当然是不对的。所以不使用cycBarr这个操作是不对的。

3.2:使用cycbarr

Java多线程工具类之循环栅栏计数器

查看运行结果:

Java多线程工具类之循环栅栏计数器

当七颗龙珠都找到之后,才可以召唤神龙。 符合我们的需求。s K ? -那么,cycbarr的实现原理是什么呢?接下来我们从源码来看看运行原理。

四:从源码来看原理及总结

4.1:构造器

Java多线程工具类之循环栅栏计数器

有两个构造器,给定一个int的parties和两个参数的构造器。参数含义:@ , 1 7 9 D t j ?

In0 1 ( v ; . b @ Qt paK q ~ lrties:给J d Z E ^定参与的线程的个数。也可以理解为屏障的值,当达到这个值之后,屏障将会跳闸执行其他任务(在集齐龙珠案例中,可以理解为需要7个线程来执行。);

R= ) n s Lunnable barrierAction:这个参数意思是指当线程达到屏障数S x S q j F C Q量后,屏障跳闸后执行给定线程的任务(在集齐龙珠案例中,可以理解为当集齐七颗龙珠后,需要执行召唤神龙的操作)。

4.2:几个重要u Q O ; M的成员属性

Java多线程工具类之循环栅栏计数器

其中使用了ReentrantLock这个可重入锁l : A * v ~ % E作为并发的锁对象。使用Codition这个对象来实o ; $ ^ 2 2 w r m现等待/通知模式。

Java多线程工具类之循环栅栏计数器

4.3:重要方法

Java多线程工具类之循环栅栏计数器

无论是await()还是await(long timeout,TimeUnit unit)这两个await最后都是调用dowait()方法。

Dowait方i : R I q ] - x法主要干了什么?其实逻辑处理x K T o @比较简单的。如: G y ]果当前线程不是最后一个调用await方法的线程,则会一直自旋等待着。源码如下:

Java多线程工具类之循环栅栏计数器

当发生以下清空的时候,就会在自旋等待了:

1:当前执行的线程是最后一个线程。即index == 0成立的时候;

2:当参与其中的某个线程在等待的时候,等待超时了;

3:参与的线程中某一个线程被3 ) ; e ; i h中断了;

4:在调用了CycBarr的reset方法后。T N [ r该方法将会将对应的屏障(pa+ O L Zrties)重置为初始状态。

对应源码如下:

Java多线程工具类之循环栅栏计数器

Java多线程工具类之循环栅栏计数器

4.P J . Y U i #4:总结

语法:

默认使用两个参数的构造器。然后再try代码块中调用await方法。如下图:

Java多线程工具类之循环栅栏计数器

五:CyclicBarrier与CountD! } W ,ownLatch比较

关于CountDownLatch的相关介绍,凯哥(kaigejava)在另一篇文章《Java多线程E v Q并发容器之并发倒计时器》中; d n N F Q R , A做了详细介绍。欢迎大家去查看.

CountDown:

计数器只能够使用一次;

参与的线程的职责是不一样的(火箭发射,不同部门做的事情不一样)。有的再倒计时,有的再等待倒计时结束。

CycBarr:

是可以循环利用的,因为可以使用reset方法将屏障重置,可以使c t M 1用多次,所有cycBar能够处理更为复杂的场景;

参与的线程职责是一样的(都h | a M m 9 i =K J % ~ $ ( o !找龙珠);

提供了其他的方法。如获取当前阻塞的线程数量的getnumberWaiting方法。用于B v U $判断当前线{ D 5 k A c L T程阻塞的线程是否被中断的isBroken方法。

从唤起阻塞线程角度来看的话:

CountDownLatch运行一个或者是多个线程等待一组事件的产生,而% , 9 * C f qCyclicBarrier用于等待其他线程运行到屏障(栅栏)位置。

从适用场景角度来说:

CycBarr适用于多个线程结果元素的合并操作。

如需要从多个excell N ] Q _ x中统计数量的时候,可以使用CycBarr来从不同L n r的excel读取到数据之后,在进行汇总操作。

上一篇

岳飞被杀是必然,解密宋高宗3个心理变化,从器重到痛下杀手

下一篇

为什么从中国飞往美国的客机,都要绕过太平洋,而不直接飞过去?

你也可能喜欢

  • 暂无相关文章!

发表评论

您的电子邮件地址不会被公开。 必填项已用 * 标注

提示:点击验证后方可评论!

插入图片
返回顶部