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


    Java多线程下循环计数器

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

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

    编辑

    一:CyclicBarrier是什么

    cycBar是什么呢?

    来看看JDKAPI文档中是怎么介绍这个对象的:

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

    有没有这种感觉:每个汉字都认识,但是放在一起就不知道什么意思了?对!没错,就是这种感觉~~~///(^v^)\~~~。上面翻译简单一句话就是:有个可以循环利用的集合点。作用就是让所有线程都到达这个集合点后,才会继续下一步行动。如果还是不理解,请看下下面生活中的例子。

    二:CyclicBarrier生活中例子理解

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

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

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

    三:代码演示

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

    3.1:未使用cycbarr的时候

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

    运行结果:

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

    3.2:使用cycbarr

    查看运行结果:

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

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

    4.1:构造器

    有两个构造器,给定一个int的parties和两个参数的构造器。参数含义:

    Int parties:给定参与的线程的个数。也可以理解为屏障的值,当达到这个值之后,屏障将会跳闸执行其他任务(在集齐龙珠案例中,可以理解为需要7个线程来执行。);

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

    4.2:几个重要的成员属性

    其中使用了ReentrantLock这个可重入锁作为并发的锁对象。使用Codition这个对象来实现等待/通知模式。

    4.3:重要方法

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

    Dowait方法主要干了什么?其实逻辑处理比较简单的。如果当前线程不是最后一个调用await方法的线程,则会一直自旋等待着。源码如下:

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

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

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

    3:参与的线程中某一个线程被中断了;

    4:在调用了CycBarr的reset方法后。该方法将会将对应的屏障(parties)重置为初始状态。

    对应源码如下:

    4.4:总结

    语法:

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

    五:CyclicBarrier与CountDownLatch比较

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

    CountDown:

    计数器只能够使用一次;

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

    CycBarr:

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

    参与的线程职责是一样的(都是找龙珠);

    提供了其他的方法。如获取当前阻塞的线程数量的getnumberWaiting方法。用于判断当前线程阻塞的线程是否被中断的isBroken方法。

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

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

    从适用场景角度来说:

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

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

        ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​    ​欢迎来聊

  • 相关阅读:
    作业5,6 2019/10/23
    作业1、2、3、4 2019/10/23
    实现Map传参Mybatis
    maven工程配置pom.xml实现mybatis的访问数据库操作
    测试
    Postman篇之命令行测试
    unittest框架
    测试
    测试
    测试
  • 原文地址:https://www.cnblogs.com/kaigejava/p/12664653.html
Copyright © 2020-2023  润新知