透过案例--了解循环栅栏
循环栅栏
- 循环栅栏
- 一、案例-司令跟士兵的日常
- 1、上demo
- 1)、代码实现
- 2)、测试结果以及小结
- ①测试结果导读
- ②小结:
- ③外层线程最后调用循环栅栏,还能否起到阻塞作用?
- 2、草图导读
- 3、番外篇
- 案例-游乐场之行~更直白
循环栅栏
一、案例-司令跟士兵的日常
别的线程和循环栅栏这俩货要合作,所以他们先进行了简单的沟通:
别的线程:一听栅栏,肯定就是有限制,据说这里的限制是阻塞我(别的线程)的,而且阻塞的个数由你(循环栅栏)来定
(假定阻塞个数是7,那么这里循环栅栏的计数器大小为7)循环栅栏:是的。别的线程:哦哦,那要是阻塞我(别的线程)的个数超过7个,是不是就让我(别的线程)执行了?循环栅栏:是的。但是这里讲的案例,既然有了我(循环栅栏)的参与,那你就要在你的run里取调用我,调用顺序看你的需要。只要你调用我了,不管怎样的调用顺序,我都会起到阻塞的作用;而且你(别的线程)可以重复使用我(循环栅栏);阻塞的计数器个数由我(循环栅栏)来定,比如设定为3,那就阻塞你(别的线程)线程的个数达到3的时候,才会调用你(别的线程)的run方法。别的线程:好的,谢谢~
上面总结:
1、循环栅栏对象可以重复使用;
2、循环栅栏计数器的值决定阻塞其他线程的个数,达到计数器个数,被阻塞的线程可以继续运行;
3、只要线程的run里调用了循环栅栏,不论执行顺序,都有阻塞的效果。
4、用法:在线程的run方法内,调用循环栅栏包裹的线程。
针对对话内容,进行了测试
在代码中,循环栅栏的用法就是线程内调用栅栏,栅栏起到阻塞的作用
1、上demo
1)、代码实现
注释掉了原来代码打印,使循环栅栏的使用情况更加清晰;
package com.test.threadStu;import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;public class CyclicBarrierDemo {public static class Soldier implements Runnable{private String soldier;private final CyclicBarrier cyclic;Soldier(CyclicBarrier cyclic,String soldierName){this.cyclic=cyclic;this.soldier=soldierName;}public void run(){try {//等待所有士兵到齐cyclic.await();doWork();//等待所有士兵完成工作cyclic.await();}catch (InterruptedException e){e.printStackTrace();}catch (BrokenBarrierException e){e.printStackTrace();}}private void doWork() {try {Thread.sleep(Math.abs(new Random().nextInt()%10000));} catch (InterruptedException e) {e.printStackTrace();}System.out.println(soldier+":任务完成-----step2:外层线程调用的工作任务");}}public static class BarrierRun implements Runnable{boolean flag;int N;public BarrierRun(boolean flag,int N){this.flag=flag;this.N=N;}public void run(){if(flag){System.out.println("司令:[士兵"+N+"个,任务完成]-----step3:循环栅栏包裹的线程任务");}else{System.out.println("司令:[士兵"+N+"个,集合完毕]-----step1:循环栅栏包裹的线程任务");flag=true;}}}public static void main(String[] args) {final int N=5;Thread[] allSoldier=new Thread[N];boolean flag=false;CyclicBarrier cyclic=new CyclicBarrier(N,new BarrierRun(flag,N));//设置屏障点,主要是为了执行这个方法// System.out.println("集合队伍!");for (int i=1;i<=N;i++){// System.out.println("士兵"+i+"报道!");allSoldier[i-1]=new Thread(new Soldier(cyclic,"士兵"+i));allSoldier[i-1].start();/* if(i==3){//标识1:调用线程终端allSoldier[i].interrupt();}*/}System.out.println("上述step123为外层线程run()方法的调用顺序");}
}
2)、测试结果以及小结
①测试结果导读
执行顺序可按实际需求来,这里执行顺序
step1: 调用栅栏 wait,意味着先阻塞Soldier线程5个数,然后执行循环栅栏包裹的线程任务【栅栏包裹的任务执行完,接着指定外层线程的核心任务】
step2: 调用线程Soldier的工作任务
step3: 调用栅栏 await ,由于123步属于线程Soldier的一次调度,而第一步已经阻塞过了,这里直接执行栅栏里包裹的线程任务。
使用当中 以上步骤1是栅栏里的,await过程按顺序干俩事:① 阻塞Soldier为栅栏计数器个数5 ②、在1之后, 执行栅栏里包裹的线程任务
上述step123为外层线程run()方法的调用顺序
司令:[士兵5个,集合完毕]-----step1:循环栅栏包裹的线程任务
士兵4:任务完成-----step2:外层线程调用的工作任务
士兵1:任务完成-----step2:外层线程调用的工作任务
士兵2:任务完成-----step2:外层线程调用的工作任务
士兵3:任务完成-----step2:外层线程调用的工作任务
士兵5:任务完成-----step2:外层线程调用的工作任务
司令:[士兵5个,任务完成]-----step3:循环栅栏包裹的线程任务
②小结:
1、在Soldier 工作任务里调度BarrierRun的线程,Soldier的线程启动触发BarrierRun启动
2、在Soldier【外层线程】里BarrierRun【循环栅栏包裹的线程】在什么时候调度看你实际需要
3、以上step步骤执行的顺序不是固定的,可根据你的实际需要执行
③外层线程最后调用循环栅栏,还能否起到阻塞作用?
答案是肯定的,稍加改动代码,
把 main里的【士兵+i+报道!】注释释放掉,
线程内循环栅栏的调用顺序,看是否还能起到阻塞的作用
看这个答案也知道,仍然起到了阻塞的作用。
士兵1报道!
士兵2报道!
士兵3报道!
士兵4报道!
士兵5报道!
上述step123为外层线程run()方法的调用顺序
士兵1:任务完成-----step2:外层线程调用的工作任务
士兵3:任务完成-----step2:外层线程调用的工作任务
士兵2:任务完成-----step2:外层线程调用的工作任务
士兵5:任务完成-----step2:外层线程调用的工作任务
士兵4:任务完成-----step2:外层线程调用的工作任务
司令:[士兵5个,集合完毕]-----step1:循环栅栏包裹的线程任务
2、草图导读
如果你经过一番纠结还是不太明白,可以参看下面的草图。
关于前置变量有问号的小伙伴从第二个图里找含义:
前置变量:
A:Soldier【外层线程】
b:BarrierRun【循环栅栏包裹的线程】
那么问题来了:
循环栅栏的使用特点:是用在一个线程的工作任务里的吗?我觉得是的,首先栅栏就是阻塞的作用,那不在被阻塞的线程里工作,他咋阻塞人家呀,您说是不?
在下才疏学浅,关于这个问题的解答,仅代表我个人观点,不一定那么回事儿,欢迎反驳~
3、番外篇
案例-士兵跟司令的日常里,code里有两个异常,可以了解下
- InterruptedException:表示等待过程中,线程被中断,这是一个非常通用的异常。大部分迫使线程等待的方法,都可能会抛出这个异常,使线程在等待时依然可以响应外部紧急事件
- BrokenBarrierException: 这个异常则是CyclicBarrier 特有的,表示当前CyclicBarrier 已经破损,系统没法等所有线程到齐了。如果继续等待可能是徒劳无功的,因此还是就地散伙,打道回府吧。如果放开主程序中"标识1"的三行代码
if(i==3){//标识1:调用线程终端allSoldier[0].interrupt();}
案例-游乐场之行~更直白
时间有限,后续会补充追加,在此标记备注
比如你去游乐场玩儿一个娱乐项目,结果每次都要排队,5人一组,才能一起玩儿一次。
循环栅栏也是一样,栅栏就是加限制,进入栅栏内才能做一些事,上述案例,栅栏的计数器是5,就是凑齐5个人,这个项目才能玩儿。
在代码中,循环栅栏的用法就是线程内调用栅栏,栅栏起到阻塞的作用,直到线程数A达到5。才会执行栅栏内要做的事(C)
栅栏的实例化需要另外一个线程(玩儿娱乐项目),有人来排队(执行外层线程A),栅栏会阻塞,直到阻塞个数达到栅栏计数器个数,
参考文献:
案例-司令跟士兵的日常-----《实战java高并发程序设计》
透过案例--了解循环栅栏相关推荐
- 非常有用的并发控制-循环栅栏CyclicBarrier
转载自 非常有用的并发控制-循环栅栏CyclicBarrier 昨天我讲了倒计时器CountDownLatch的应用,它是阻塞线程直到计时器归0的一种等待方式.今天讲的这个循环栅栏CyclicBarr ...
- 信号量semaphore 读写锁ReadWriteLock 倒计时器CountDownLatch 循环栅栏 CyclicBarrier 线程阻塞工具类LockSupport...
信号量semaphore 允许多个线程同时访问 读写锁ReadWriteLock 在频繁的读写耗时中,读之间不阻塞 倒计时器CountDownLatch obj = new Count ...
- 同步工具之CyclicBarrier循环栅栏
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门, ...
- 循环计数_倒计数器:CountDownLatch | 循环栅栏:CyclicBarrier
倒计数器:CountDownLatch CountDownLatch 从名字就可以看出其作用:初始化一个计数,然后每次递减,直至为0,然后触发一个动作.只有一个带参构造器: CountDownLatc ...
- CyclicBarrier: 循环栅栏
CyclicBarrier是另外一种多线程并发控制工具.和CountDownLatch非常类似,它也可以实现线程间的计数等待,但它的功能比CountDownLatch更加复杂且强大. CyclicBa ...
- Java并发编程系列学习_CountDownLatch倒计时器CyclicBarrier循环栅栏
一.倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方 ...
- 倒计时器CountDownLatch 和 循环栅栏:CyclicBarrier
一 概念: 1.在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方法,让主线程等待被join ...
- python画三维几何图形拼成的图案_Scratch3.0少儿编程案例:循环画窗花
一.案例简介 窗花艺术是我国非物质文化遗产,每逢过年过节的时候,家家户户都在窗户上贴满窗花.今天我们就来用scratch 3.0来制作少儿编程案例:循环画窗花.简单的窗花图案都是对称的,由多个重复的简 ...
- CyclicBarrie(循环栅栏)的作用与用法
CyclicBarrie的作用与用法 一.CyclicBarrie的作用 CyclicBarrier循环栅栏(循环屏障)是一个多线程同步的辅助工具类,它允许一组线程在到达某个等待屏障点(common ...
- 循环栅栏 CycleBarrier 理解到深入
关于 CycleBarrier Java JUC 包中提供类似的工具,可以设置一个简单的集合点,等所有成员到齐了之后,再执行下一步操作.CycleBarrier 它就相当于是一个栅栏,所有线程在到达栅 ...
最新文章
- Linux命令之whereis
- PostgreSQL数据库设置远程连接
- boost::hana::replace用法的测试程序
- RESTful 架构详解
- 华为ensp小实验(路由下发+Easy IP+单臂路由+OSPF+Rip)
- 机器学习第十篇:如何评价模型效果评估
- BZOJ 4753 二分+树形DP
- 微型计算机2020年5月上,2020年小进初微机派位细则出炉,意向民办最多可参加3次派位!...
- Linux 安装Eclipse
- Saltstack远程执行命令(3)
- 让你的U盘变光驱,制作USB-CDROM,用U盘安装系统
- Unity游戏iOS AppStore 内付费接入(In app purchase)
- Git三大特色之Stage(暂存区)--留着当资料
- 蛋白互作常用的研究方法
- JAVA除数为0报错?
- android视频拷到iphone6,苹果和安卓手机保存B站视频到U盘方法介绍
- VirtualBox调试分辨率时遇到的问题
- 17.项目开发中遇到的问题(this.$parent.$parent子组件调父组件的父组件的方法不可用问题)
- 阳光下可读显示技术的工作原理
- ntfs硬盘如何在mac上读写移动硬盘文件?
热门文章
- ORR和BIC伪指令应用
- Python pandas.DataFrame.add_suffix函数方法的使用
- Java 嵌入数据处理引擎:SQLite 的挑战者
- git报错 warning: Clone succeeded, but checkout failed.
- 解决Jar包双击打不开!
- Cousera吴恩达机器学习week8笔记
- python常见容器操作:字符串的增删改查循环、列表的增删改查循环、元组的查循环、字典的的增删改查循环等常规操作
- 乔巴机器人 番外篇_超神学院之暮光之眼
- C++模板的类的展开
- 思杰 Citrix ADC产品介绍