zoukankan      html  css  js  c++  java
  • 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读取到数据之后,在进行汇总操作。

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

  • 相关阅读:
    跃迁方法论 Continuous practice
    EPI online zoom session 面试算法基础知识直播分享
    台州 OJ 2648 小希的迷宫
    洛谷 P1074 靶形数独
    洛谷 P1433 DP 状态压缩
    台州 OJ FatMouse and Cheese 深搜 记忆化搜索
    台州 OJ 2676 Tree of Tree 树状 DP
    台州 OJ 2537 Charlie's Change 多重背包 二进制优化 路径记录
    台州 OJ 2378 Tug of War
    台州 OJ 2850 Key Task BFS
  • 原文地址:https://www.cnblogs.com/kaigejava/p/12664653.html
Copyright © 2011-2022 走看看