CyclicBarrier,一个同步辅助类,在API中是这么介绍的:

它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

通俗点讲就是:让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。

先可以看下测试结果:

等待线程进来之后并没有立即去执行相关业务逻辑,当线程达到你设计的要求之后才回去执行相关业务逻辑数据,测试代码如下

  1. package com.cxy.cyclicBarrier;
  2.  
  3. import java.util.concurrent.BrokenBarrierException;
  4. import java.util.concurrent.CyclicBarrier;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7.  
  8. /**
  9. * Created by Administrator on 2017/4/10.
  10. */
  11. public class CyclicBarrierDemo {
  12. private static CyclicBarrier cyclicBarrier=new CyclicBarrier();
  13.  
  14. public static void main(String[] args) throws InterruptedException {
  15. ExecutorService executorService = Executors.newCachedThreadPool();
  16. for (int i =;i< ;i++){
  17. System.out.println("创建线程"+i);
  18. final int threadNum =i;
  19. Thread.sleep();
  20. executorService.execute( ()->{
  21. try {
  22. cxyDemo(threadNum);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. } catch (BrokenBarrierException e) {
  26. e.printStackTrace();
  27. }
  28. });
  29. }
  30. executorService.shutdown();
  31.  
  32. }
  33. private static void cxyDemo(int threadNum) throws InterruptedException, BrokenBarrierException {
  34. Thread.sleep();
  35. System.out.println(Thread.currentThread().getName() + "开始等待其他线程");
  36. cyclicBarrier.await();
  37. System.out.println(threadNum);
  38.  
  39. }
  40. }

其中利用到lamba表达式,

利用到可缓存的线程池,可以其中有个注释不是很对

  1. public CyclicBarrier(int parties, Runnable barrierAction) {
  2. if (parties <= ) throw new IllegalArgumentException();
  3. this.parties = parties;
  4. this.count = parties;
  5. this.barrierCommand = barrierAction;
  6. }
  7.  
  8. /**
  9. * Creates a new {@code CyclicBarrier} that will trip when the
  10. * given number of parties (threads) are waiting upon it, and
  11. * does not perform a predefined action when the barrier is tripped.
  12. *
  13. * @param parties the number of threads that must invoke {@link #await}
  14. * before the barrier is tripped
  15. * @throws IllegalArgumentException if {@code parties} is less than 1
  16. */
  17. public CyclicBarrier(int parties) {
  18. this(parties, null);
  19. }

两个构造方法:

第一个需要传入线程数,还有就是Runnable

第二个 需要传入得线程数

这个参数定义的线程数,当线程数到设置的值,那么就回去执行awit方法后面的逻辑

在我上面案例中使用的是第一种构造方法:

下面将使用第二种案例:

  1. package com.cxy.cyclicBarrier;
  2.  
  3. import java.util.concurrent.BrokenBarrierException;
  4. import java.util.concurrent.CyclicBarrier;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7.  
  8. /**
  9. * Created by Administrator on 2017/4/10.
  10. */
  11. public class CyclicBarrierDemo {
  12. /* private static CyclicBarrier cyclicBarrier=new CyclicBarrier(10);
  13.  
  14. public static void main(String[] args) throws InterruptedException {
  15. ExecutorService executorService = Executors.newCachedThreadPool();
  16. for (int i =0;i< 10;i++){
  17. System.out.println("创建线程"+i);
  18. final int threadNum =i;
  19. Thread.sleep(1000);
  20. executorService.execute( ()->{
  21. try {
  22. cxyDemo(threadNum);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. } catch (BrokenBarrierException e) {
  26. e.printStackTrace();
  27. }
  28. });
  29. }
  30. executorService.shutdown();
  31.  
  32. }
  33. private static void cxyDemo(int threadNum) throws InterruptedException, BrokenBarrierException {
  34. Thread.sleep(1000);
  35. System.out.println(Thread.currentThread().getName() + "开始等待其他线程");
  36. cyclicBarrier.await();
  37. System.out.println(threadNum);
  38.  
  39. }*/
  40. private static CyclicBarrier cyclicBarrier;
  41.  
  42. static class CyclicBarrierThread extends Thread {
  43. public void run() {
  44. System.out.println(Thread.currentThread().getName() + "到了"); //等待
  45. try {
  46. cyclicBarrier.await();
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }
  52.  
  53. public static void main(String[] args) {
  54. cyclicBarrier = new CyclicBarrier(, new Runnable() {
  55. @Override
  56. public void run() {
  57. System.out.println("人到齐了,开始吧....");
  58. }
  59. });
  60. for (int i = ; i < ; i++) {
  61. new CyclicBarrierThread().start();
  62. }
  63. }
  64. }

执行结果:

那么await方法到底干了什么呢:

  1. public int await() throws InterruptedException, BrokenBarrierException {
  2. try {
  3. return dowait(false, 0L);
  4. } catch (TimeoutException toe) {
  5. throw new Error(toe); // cannot happen
  6. }
  7. }

最终调用的dowait方法: /**

  1. * Main barrier code, covering the various policies.
  2. */
  3. private int dowait(boolean timed, long nanos)
  4. throws InterruptedException, BrokenBarrierException,
  5. TimeoutException {
  6.       //实现锁,安全
  7. final ReentrantLock lock = this.lock;
  8. lock.lock();
  9. try {
  10. final Generation g = generation;
  11.         //分代被破坏,异常抛出
  12. if (g.broken)
  13. throw new BrokenBarrierException();
  14. if (Thread.interrupted()) {
              //线程被中断,
  15. breakBarrier();
  16. throw new InterruptedException();
  17. }
  18.         //线程进来,减少数据量
  19. int index = --count;
  20. if (index == ) { // tripped
              // 达到指定的数量时候,执行
  21. boolean ranAction = false;
  22. try {
  23. final Runnable command = barrierCommand;
  24. if (command != null)
  25. command.run();
                //唤醒线程
  26. ranAction = true;
                //更新分代
  27. nextGeneration();
  28. return ;
  29. } finally {
  30. if (!ranAction)
  31. breakBarrier();
  32. }
  33. }
  34. // loop until tripped, broken, interrupted, or timed out
  35. for (;;) {
  36. try {
  37. if (!timed)
  38. trip.await();
  39. else if (nanos > 0L)
  40. nanos = trip.awaitNanos(nanos);
  41. } catch (InterruptedException ie) {
  42. if (g == generation && ! g.broken) {
  43. breakBarrier();
  44. throw ie;
  45. } else {
  46. // We're about to finish waiting even if we had not
  47. // been interrupted, so this interrupt is deemed to
  48. // "belong" to subsequent execution.
  49. Thread.currentThread().interrupt();
  50. }
  51. }
  52. if (g.broken)
  53. throw new BrokenBarrierException();
  54. if (g != generation)
  55. return index;
  56. if (timed && nanos <= 0L) {
  57. breakBarrier();
  58. throw new TimeoutException();
  59. }
  60. }
  61. } finally {
            //最终释放锁
  62. lock.unlock();
  63. }
  64. }
  • 最后一个线程到达,即index == 0
  • 超出了指定时间(超时等待)
  • 其他的某个线程中断当前线程
  • 其他的某个线程中断另一个等待的线程
  • 其他的某个线程在等待barrier超时
  • 其他的某个线程在此barrier调用reset()方法。reset()方法用于将屏障重置为初始状态

应用场景;开会,还有就是例如现金很火的游戏,只有等待大家准备好了,才开始执行进入房间

JUC包下CyclicBarrier学习笔记的更多相关文章

  1. JUC包下Semaphore学习笔记

    在Java的并发包中,Semaphore类表示信号量.Semaphore内部主要通过AQS(AbstractQueuedSynchronizer)实现线程的管理.Semaphore有两个构造函数,参数 ...

  2. JUC包下CountDownLatch学习笔记

    CountDownLatch的作用是能使用多个线程进来之后,且线程任务执行完毕之后,才执行, 闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态.通俗的讲就是,一个闭锁相当于 ...

  3. Linux下iptables学习笔记

    Linux下iptables学习笔记 在Centos7版本之后,防火墙应用已经由从前的iptables转变为firewall这款应用了.但是,当今绝大多数的Linux版本(特别是企业中)还是使用的6. ...

  4. YOLO---Darknet下的学习笔记 V190319

    YOLO---Darknet下的学习笔记 @WP 20190319 很久没有用YOlO算法了,今天又拿过来玩玩.折腾半天,才好运行通的,随手记一下: 一是,终端下的使用.二是,python接口的使用. ...

  5. YOLO---Darknet下的学习笔记

    YOLO.V3-Darknet下的学习笔记 @wp20180927 [目录] 一. 安装Darknet(仅CPU下) 2 1.1在CPU下安装Darknet方式 2 1.2在GPU下安装Darknet ...

  6. JUC.Lock(锁机制)学习笔记[附详细源码解析]

    锁机制学习笔记 目录: CAS的意义 锁的一些基本原理 ReentrantLock的相关代码结构 两个重要的状态 I.AQS的state(int类型,32位) II.Node的waitStatus 获 ...

  7. 20135202闫佳歆--week5 系统调用(下)--学习笔记

    此为个人笔记存档 week 5 系统调用(下) 一.给MenuOS增加time和time-asm命令 这里老师示范的时候是已经做好的了: rm menu -rf 强制删除 git clone http ...

  8. juc包:使用 juc 包下的显式 Lock 实现线程间通信

    一.前置知识 线程间通信三要素: 多线程+判断+操作+通知+资源类. 上面的五个要素,其他三个要素就是普通的多线程程序问题,那么通信就需要线程间的互相通知,往往伴随着何时通信的判断逻辑. 在 java ...

  9. 【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore

    前言 JUC中为了满足在并发编程中不同的需求,提供了几个工具类供我们使用,分别是CountDownLatch.CyclicBarrier和Semaphore,其原理都是使用了AQS来实现,下面分别进行 ...

随机推荐

  1. 各大IT/IC公司offer比较&nbsp;

    1:本人西电通院2013届毕业硕士,根据今年找工作的情况以及身边同学的汇总,总结各大公司的待遇如下,吐血奉献给各位学弟学妹,公司比较全,你想去的公司不在这里面,基本上是无名小公司了:但无名小公司有时也 ...

  2. java基础面试题 背过1

    web.xml文件中可以配置哪些内容? 答:web.xml用于配置Web应用的相关信息,如:监听器(listener) ContextLoaderListener .过滤器(filter) Strut ...

  3. 16.数据类型(data_type)

    CREATE TABLE 语句 CREATE TABLE 语句用于创建数据库中的表. SQL CREATE TABLE 语法 CREATE TABLE 表名称 ( 列名称1 数据类型, 列名称2 数据 ...

  4. Luogu 4244 [SHOI2008]仙人掌图

    BZOJ 1023 如果我们把所有的环都缩成一个点,那么整张图就变成了一棵树,我们可以直接$dp$算出树的直径. 设$f_x$表示$x$的子树中最长链的长度,那么对于$x$的每一个儿子$y$,先用$f ...

  5. ShopNc实例化对象

    1.模型 $model_member = Model('member'); 2.接口 require_once BASE_ROOT_PATH.'/member/api/smiMember/action ...

  6. MySQL——explain性能分析的使用

    用法:explain sql语句: id:查询的序号. ref:进行连接查询时,表得连接关系.可以通过上图看出. select_type:select查询的类型,主要是区别普通查询和联合查询.子查询之 ...

  7. VS code docker 调试 asp.net core

    前言 .net core的诞生就是为了解决跨平台的事情的,所以.net core app运行在linux.macOS.docker上也不是什么新鲜事了. 相信已经有不少.net core的项目已经部署 ...

  8. oracle数据库创建表

    实际工作中,在数据库中创建表是经常会用到的.我们今天呢?主要给大家来分享一下在数据库如何通过sql语句去创建表.其实,创建表很简单,只需要把数据库的数据类型和约束搞清楚就可以了,其他的就好说了.接下来 ...

  9. C#序列化xml,开发常用

    序列化操作对于开发人员来说最熟悉不过了. 序列化分为:序列化和反序列化. 序列化名词解释:序列化是将对象状态转换为可保持或传输的格式的过程. 与序列化相对的是反序列化,它将流转换为对象.这两个过程结合 ...

  10. c++基础之向量Vector

    首先和string一样要在开头 #include <vector> #include <string> 和string一样,也算是一种容器,而且同属于STL(standard ...