CyclicBarrie的作用与用法

一、CyclicBarrie的作用
CyclicBarrier循环栅栏(循环屏障)是一个多线程同步的辅助工具类,它允许一组线程在到达某个等待屏障点(common barrier point)互相等待,发生阻塞,直到最后一个线程到达等待屏障点,屏障才会打开,之前处于阻塞状态的线程才能恢复继续执行.它非常适用于一组线程之间必需经常互相等待的情况。

CyclicBarrier从字面理解是循环的栅栏,之所以称之为循环的是因为在等待线程释放后,该栅栏还可以复用。后面我们代码中会进行体现;
CyclicBarrier和CountDownLatch不同,CountDownLatch是一次性使用的,也就是说latch门闩只能只用一次,一旦latch门闩被打开就不能再次关闭,将会一直保持打开状态。

二、CyclicBarrier类中定义的一些方法

  1. 构造方法:必传参数,参与等待的线程数量
 /*** Creates a new {@code CyclicBarrier} that will trip when the* given number of parties (threads) are waiting upon it, and* does not perform a predefined action when the barrier is tripped.** @param parties the number of threads that must invoke {@link #await}*        before the barrier is tripped* @throws IllegalArgumentException if {@code parties} is less than 1*/public CyclicBarrier(int parties) {this(parties, null);}
  1. 构造方法:参与等待的线程数量一级屏障线程的构造方法
/*** Creates a new {@code CyclicBarrier} that will trip when the* given number of parties (threads) are waiting upon it, and which* will execute the given barrier action when the barrier is tripped,* performed by the last thread entering the barrier.** @param parties the number of threads that must invoke {@link #await}*        before the barrier is tripped* @param barrierAction the command to execute when the barrier is*        tripped, or {@code null} if there is no action* @throws IllegalArgumentException if {@code parties} is less than 1*/public CyclicBarrier(int parties, Runnable barrierAction) {if (parties <= 0) throw new IllegalArgumentException();this.parties = parties;this.count = parties;this.barrierCommand = barrierAction;}
  1. 获取参与使用栅栏(屏障)的线程数量
/*** Returns the number of parties required to trip this barrier.** @return the number of parties required to trip this barrier*/public int getParties() {return parties;}
  1. 线程中设置的屏障点,也就是线程执行到这行代码的时候,则进入等待阻塞状态
 public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);} catch (TimeoutException toe) {throw new Error(toe); // cannot happen}}
  1. 返回当前在屏障处等待的参与方数。此方法主要用于调试和断言。
 /*** Returns the number of parties currently waiting at the barrier.* This method is primarily useful for debugging and assertions.** @return the number of parties currently blocked in {@link #await}*/public int getNumberWaiting() {final ReentrantLock lock = this.lock;lock.lock();try {return parties - count;} finally {lock.unlock();}}
  1. 获取是否破损标志位broken的值,此值有以下几种情况
1.CyclicBarrier初始化时,broken=false,表示屏障未破损。
2.如果正在等待的线程被中断,则broken=true,表示屏障破损。
3..如果正在等待的线程超时,则broken=true,表示屏障破损。
4.如果有线程调用CyclicBarrier.reset()方法,则broken=false,表示屏障回到未破损状态。
 /*** Queries if this barrier is in a broken state.** @return {@code true} if one or more parties broke out of this*         barrier due to interruption or timeout since*         construction or the last reset, or a barrier action*         failed due to an exception; {@code false} otherwise.*/public boolean isBroken() {final ReentrantLock lock = this.lock;lock.lock();try {return generation.broken;} finally {lock.unlock();}}
  1. 重新设置CyclicBarrier到初始状态,该方法主要完成两个动作;
1.将是否破损标志位broken置为false。参考内部方法:breakBarrier()-----将当前的屏障设置为“已破坏”,并唤醒所有人
2.如果有正在等待的线程,则会抛出BrokenBarrierException异常,且这些线程停止等待,继续执行。参考内部方法:nextGeneration()  ---更新屏障行程状态并唤醒所有人
    /*** Resets the barrier to its initial state.  If any parties are* currently waiting at the barrier, they will return with a* {@link BrokenBarrierException}. Note that resets <em>after</em>* a breakage has occurred for other reasons can be complicated to* carry out; threads need to re-synchronize in some other way,* and choose one to perform the reset.  It may be preferable to* instead create a new barrier for subsequent use.*/public void reset() {final ReentrantLock lock = this.lock;lock.lock();try {breakBarrier();   // break the current generationnextGeneration(); // start a new generation} finally {lock.unlock();}}/*** Sets current barrier generation as broken and wakes up everyone.* Called only while holding lock.*/private void breakBarrier() {generation.broken = true;count = parties;trip.signalAll();}/*** Updates state on barrier trip and wakes up everyone.* Called only while holding lock.*/private void nextGeneration() {// signal completion of last generationtrip.signalAll();// set up next generationcount = parties;generation = new Generation();}

三、CyclicBarrier具体使用代码样例

package com.demo.spring.test.baseThread;import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @Description:  循环栅栏多线程同步工具类*/
public class CyclicBarrierDemo implements Runnable{CyclicBarrier cyclicBarrier;public CyclicBarrierDemo(CyclicBarrier cyclicBarrier){this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName()+"开始执行");System.out.println("模拟异步发送短信邮件,发送完成");// 任务中需要等待其它线程全部执行到这个位置等待cyclicBarrier.await();System.out.println(Thread.currentThread().getName()+"等待结束");} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {// 我们设置有5个线程的循环栅栏CyclicBarrier cyclicBarrier = new CyclicBarrier(5);ExecutorService pool = Executors.newCachedThreadPool();try {// 为了体现循环栅栏可循环使用,我们用10个循环线程;// 如果是可循环使用的,当有5个线程第一次使用完以后,程序会继续完成执行;// 同时,另外5个线程也会因为再此获取到CyclicBarrier实例而继续往下执行;for(int i = 0; i < 10; i++){CyclicBarrierDemo demo = new CyclicBarrierDemo(cyclicBarrier);pool.execute(demo);}}finally {pool.shutdown();}System.out.println("5个任务执行完成,继续往下进行业务处理");}
}

上面代码的执行结果:

pool-1-thread-2开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-1开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-3开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-4开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-5开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-6开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-7开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-5等待结束
pool-1-thread-2等待结束
pool-1-thread-8开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-4等待结束
pool-1-thread-9开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-3等待结束
pool-1-thread-1等待结束
5个任务执行完成,继续往下进行业务处理
pool-1-thread-10开始执行
模拟异步发送短信邮件,发送完成
pool-1-thread-10等待结束
pool-1-thread-9等待结束
pool-1-thread-8等待结束
pool-1-thread-7等待结束
pool-1-thread-6等待结束

分析以上结果:优先等待结束的线程数:5,2,4,3,1,也就是说这5个线程第一轮占用了cyclicBarrier;那么,既然cyclicBarrier是可循环复用的,剩下的另外也能占用cyclicBarrier,只不过剩下的是在第一轮用完以后.
我们继续看显示的结果,找到:“5个任务执行完成,继续往下进行业务处理”这行结果,可见,第一次5个线程用完cyclicBarrier以后,main主程序方法继续往下执行,同时,在第10个线程完成到达屏障点以后,10,9,8,7,6这5个线程也等待结束,继续执行线程内其它的业务代码;即文章开头所说的,它是可以复用的。

CyclicBarrie(循环栅栏)的作用与用法相关推荐

  1. PreTranslateMessage作用和用法

    PreTranslateMessage作用和用法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用,当 ...

  2. php中pre标签,html中pre标签与code标签的作用与用法

    HTML 标签 定义和用法 pre 元素可定义预格式化的文本.被包围在 pre 元素中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. 标签的一个常见应用就是用来表示计算机的源代码. 可以导致 ...

  3. 同步工具之CyclicBarrier循环栅栏

    CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门, ...

  4. 循环计数_倒计数器:CountDownLatch | 循环栅栏:CyclicBarrier

    倒计数器:CountDownLatch CountDownLatch 从名字就可以看出其作用:初始化一个计数,然后每次递减,直至为0,然后触发一个动作.只有一个带参构造器: CountDownLatc ...

  5. Java并发编程系列学习_CountDownLatch倒计时器CyclicBarrier循环栅栏

    一.倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方 ...

  6. chatgpt赋能python:**Python取余符号:了解%运算符的作用和用法**

    Python取余符号:了解%运算符的作用和用法 作为一名有着10年编程经验的工程师,我对Python这门编程语言深有了解.在本文中,我将详细介绍Python的取余符号,即%运算符,其作用和用法. 什么 ...

  7. python set类型和set()函数作用、用法等集合,让你学会用set

    本文主要收集整理Python set的类型.作用.用法等知识点的收集整理,Python set是什么意思,看完本文的文章集合基本就会使用Python set了. 1.Python-set() 函数 2 ...

  8. break的作用与用法

    11.1.1 break的作用与用法 循环就象绕圈子.比如,体育课,跑1200米,跑道一圈400米,所以我们要做的事就是一边跑一边在心里计数(当然要已数,否则老师万一少计一圈,我们可就玩完了),当计数 ...

  9. java package作用_java import、package作用与用法

    java import.package作用与用法 有些人写了一阵子Java,可是对於Java 的package 跟import 还是不太了解很多人以為原始码 .java 档案中的import 会让编译 ...

最新文章

  1. ftp connect: No route to host 解决过程
  2. java非打印字符,使用Java正则表达式匹配不可打印字符
  3. 我的收藏 - 音频处理相关网站
  4. Comet OJ - Contest #11 题解赛后总结
  5. oracle查看分区表
  6. 项目测试日报模板整理
  7. Postman最新版本汉化教程
  8. ignite java,Ignite 之计算运用的 Hello world
  9. c语言计算sum,C++ partial_sum(STL partial_sum)部分和计算方法详解
  10. 8.9.2 疯狂填词
  11. Padding Oracle攻击(POODLE)技术分析
  12. 卷积自编码器(Convolutional Autoencoder)的一个实验
  13. Linux系统网络环境配置(初学者必看)!!
  14. 跨境电商亚马逊需要多少成本及运营亚马逊难吗
  15. ios IDP/IEP证书申请测试用
  16. Vue入门练习:小王记事本
  17. WEB自动化_告警框处理(对话框、确认框、提示框、输入/编辑框、勾选框、单选框、复选框、下拉框)
  18. python列表中获取最长的字符串
  19. Barcode Reader SDK5.xCrack,条形码识别支持多种文档和图像格式
  20. matlab一些指令

热门文章

  1. 中间件的地图发布数据源详解
  2. python打印报错信息_python打印当前文件错误行的简单示例
  3. 代码静态检查之findbugs
  4. android 继承relativelayout,Android自定义View(RelativeLayout),并嵌套(recyclerView)
  5. 最低通行费 C++(PTA)
  6. Qt实现文字滚动、翻动动画
  7. 在桌面新建xls格式工作表打开提示“与扩展名不匹配,文件可能已损坏或不安全,除非您信任其来源,否则请勿打开,是否仍要打开它?”
  8. 009 如何更好地进行沟通
  9. Question2Answer(Q2A)如何修改帖子的最大字数限制8000个字符?
  10. 赛狐ERP|亚马逊卖家如何利用邮件推广,邮件中这些词不能出现!