CyclicBarrie(循环栅栏)的作用与用法
CyclicBarrie的作用与用法
一、CyclicBarrie的作用
CyclicBarrier循环栅栏(循环屏障)是一个多线程同步的辅助工具类,它允许一组线程在到达某个等待屏障点(common barrier point)互相等待,发生阻塞,直到最后一个线程到达等待屏障点,屏障才会打开,之前处于阻塞状态的线程才能恢复继续执行.它非常适用于一组线程之间必需经常互相等待的情况。
CyclicBarrier从字面理解是循环的栅栏,之所以称之为循环的是因为在等待线程释放后,该栅栏还可以复用。后面我们代码中会进行体现;
CyclicBarrier和CountDownLatch不同,CountDownLatch是一次性使用的,也就是说latch门闩只能只用一次,一旦latch门闩被打开就不能再次关闭,将会一直保持打开状态。
二、CyclicBarrier类中定义的一些方法
- 构造方法:必传参数,参与等待的线程数量
/*** 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);}
- 构造方法:参与等待的线程数量一级屏障线程的构造方法
/*** 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;}
- 获取参与使用栅栏(屏障)的线程数量
/*** 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;}
- 线程中设置的屏障点,也就是线程执行到这行代码的时候,则进入等待阻塞状态
public int await() throws InterruptedException, BrokenBarrierException {try {return dowait(false, 0L);} catch (TimeoutException toe) {throw new Error(toe); // cannot happen}}
- 返回当前在屏障处等待的参与方数。此方法主要用于调试和断言。
/*** 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();}}
- 获取是否破损标志位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();}}
- 重新设置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(循环栅栏)的作用与用法相关推荐
- PreTranslateMessage作用和用法
PreTranslateMessage作用和用法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用,当 ...
- php中pre标签,html中pre标签与code标签的作用与用法
HTML 标签 定义和用法 pre 元素可定义预格式化的文本.被包围在 pre 元素中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. 标签的一个常见应用就是用来表示计算机的源代码. 可以导致 ...
- 同步工具之CyclicBarrier循环栅栏
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门, ...
- 循环计数_倒计数器:CountDownLatch | 循环栅栏:CyclicBarrier
倒计数器:CountDownLatch CountDownLatch 从名字就可以看出其作用:初始化一个计数,然后每次递减,直至为0,然后触发一个动作.只有一个带参构造器: CountDownLatc ...
- Java并发编程系列学习_CountDownLatch倒计时器CyclicBarrier循环栅栏
一.倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方 ...
- chatgpt赋能python:**Python取余符号:了解%运算符的作用和用法**
Python取余符号:了解%运算符的作用和用法 作为一名有着10年编程经验的工程师,我对Python这门编程语言深有了解.在本文中,我将详细介绍Python的取余符号,即%运算符,其作用和用法. 什么 ...
- python set类型和set()函数作用、用法等集合,让你学会用set
本文主要收集整理Python set的类型.作用.用法等知识点的收集整理,Python set是什么意思,看完本文的文章集合基本就会使用Python set了. 1.Python-set() 函数 2 ...
- break的作用与用法
11.1.1 break的作用与用法 循环就象绕圈子.比如,体育课,跑1200米,跑道一圈400米,所以我们要做的事就是一边跑一边在心里计数(当然要已数,否则老师万一少计一圈,我们可就玩完了),当计数 ...
- java package作用_java import、package作用与用法
java import.package作用与用法 有些人写了一阵子Java,可是对於Java 的package 跟import 还是不太了解很多人以為原始码 .java 档案中的import 会让编译 ...
最新文章
- ftp connect: No route to host 解决过程
- java非打印字符,使用Java正则表达式匹配不可打印字符
- 我的收藏 - 音频处理相关网站
- Comet OJ - Contest #11 题解赛后总结
- oracle查看分区表
- 项目测试日报模板整理
- Postman最新版本汉化教程
- ignite java,Ignite 之计算运用的 Hello world
- c语言计算sum,C++ partial_sum(STL partial_sum)部分和计算方法详解
- 8.9.2 疯狂填词
- Padding Oracle攻击(POODLE)技术分析
- 卷积自编码器(Convolutional Autoencoder)的一个实验
- Linux系统网络环境配置(初学者必看)!!
- 跨境电商亚马逊需要多少成本及运营亚马逊难吗
- ios IDP/IEP证书申请测试用
- Vue入门练习:小王记事本
- WEB自动化_告警框处理(对话框、确认框、提示框、输入/编辑框、勾选框、单选框、复选框、下拉框)
- python列表中获取最长的字符串
- Barcode Reader SDK5.xCrack,条形码识别支持多种文档和图像格式
- matlab一些指令
热门文章
- 中间件的地图发布数据源详解
- python打印报错信息_python打印当前文件错误行的简单示例
- 代码静态检查之findbugs
- android 继承relativelayout,Android自定义View(RelativeLayout),并嵌套(recyclerView)
- 最低通行费 C++(PTA)
- Qt实现文字滚动、翻动动画
- 在桌面新建xls格式工作表打开提示“与扩展名不匹配,文件可能已损坏或不安全,除非您信任其来源,否则请勿打开,是否仍要打开它?”
- 009 如何更好地进行沟通
- Question2Answer(Q2A)如何修改帖子的最大字数限制8000个字符?
- 赛狐ERP|亚马逊卖家如何利用邮件推广,邮件中这些词不能出现!