循环栅栏

  • 循环栅栏
    • 一、案例-司令跟士兵的日常
      • 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高并发程序设计》

透过案例--了解循环栅栏相关推荐

  1. 非常有用的并发控制-循环栅栏CyclicBarrier

    转载自 非常有用的并发控制-循环栅栏CyclicBarrier 昨天我讲了倒计时器CountDownLatch的应用,它是阻塞线程直到计时器归0的一种等待方式.今天讲的这个循环栅栏CyclicBarr ...

  2. 信号量semaphore 读写锁ReadWriteLock 倒计时器CountDownLatch 循环栅栏 CyclicBarrier 线程阻塞工具类LockSupport...

    信号量semaphore    允许多个线程同时访问 读写锁ReadWriteLock   在频繁的读写耗时中,读之间不阻塞 倒计时器CountDownLatch    obj = new Count ...

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

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

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

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

  5. CyclicBarrier: 循环栅栏

    CyclicBarrier是另外一种多线程并发控制工具.和CountDownLatch非常类似,它也可以实现线程间的计数等待,但它的功能比CountDownLatch更加复杂且强大. CyclicBa ...

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

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

  7. 倒计时器CountDownLatch 和 循环栅栏:CyclicBarrier

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

  8. python画三维几何图形拼成的图案_Scratch3.0少儿编程案例:循环画窗花

    一.案例简介 窗花艺术是我国非物质文化遗产,每逢过年过节的时候,家家户户都在窗户上贴满窗花.今天我们就来用scratch 3.0来制作少儿编程案例:循环画窗花.简单的窗花图案都是对称的,由多个重复的简 ...

  9. CyclicBarrie(循环栅栏)的作用与用法

    CyclicBarrie的作用与用法 一.CyclicBarrie的作用 CyclicBarrier循环栅栏(循环屏障)是一个多线程同步的辅助工具类,它允许一组线程在到达某个等待屏障点(common ...

  10. 循环栅栏 CycleBarrier 理解到深入

    关于 CycleBarrier Java JUC 包中提供类似的工具,可以设置一个简单的集合点,等所有成员到齐了之后,再执行下一步操作.CycleBarrier 它就相当于是一个栅栏,所有线程在到达栅 ...

最新文章

  1. Linux命令之whereis
  2. PostgreSQL数据库设置远程连接
  3. boost::hana::replace用法的测试程序
  4. RESTful 架构详解
  5. 华为ensp小实验(路由下发+Easy IP+单臂路由+OSPF+Rip)
  6. 机器学习第十篇:如何评价模型效果评估
  7. BZOJ 4753 二分+树形DP
  8. 微型计算机2020年5月上,2020年小进初微机派位细则出炉,意向民办最多可参加3次派位!...
  9. Linux 安装Eclipse
  10. Saltstack远程执行命令(3)
  11. 让你的U盘变光驱,制作USB-CDROM,用U盘安装系统
  12. Unity游戏iOS AppStore 内付费接入(In app purchase)
  13. Git三大特色之Stage(暂存区)--留着当资料
  14. 蛋白互作常用的研究方法
  15. JAVA除数为0报错?
  16. android视频拷到iphone6,苹果和安卓手机保存B站视频到U盘方法介绍
  17. VirtualBox调试分辨率时遇到的问题
  18. 17.项目开发中遇到的问题(this.$parent.$parent子组件调父组件的父组件的方法不可用问题)
  19. 阳光下可读显示技术的工作原理
  20. ntfs硬盘如何在mac上读写移动硬盘文件?

热门文章

  1. ORR和BIC伪指令应用
  2. Python pandas.DataFrame.add_suffix函数方法的使用
  3. Java 嵌入数据处理引擎:SQLite 的挑战者
  4. git报错 warning: Clone succeeded, but checkout failed.
  5. 解决Jar包双击打不开!
  6. Cousera吴恩达机器学习week8笔记
  7. python常见容器操作:字符串的增删改查循环、列表的增删改查循环、元组的查循环、字典的的增删改查循环等常规操作
  8. 乔巴机器人 番外篇_超神学院之暮光之眼
  9. C++模板的类的展开
  10. 思杰 Citrix ADC产品介绍