先做总结

1、CyclicBarrier 是什么?

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到要求的线程到达都屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。

2、CyclicBarrier 实现原理:

  private static class Generation { // 内部类,当有parties个线程到达barrier,就会更新换代
    boolean broken = false; // 是否损坏
  }
  private final ReentrantLock lock = new ReentrantLock(); // 重入锁
  private final Condition trip = lock.newCondition();提供一个条件等待队列
  private final int parties; // 等待线程总数量
  private final Runnable barrierCommand; // 达到等待线程数量后执行的线程
  private Generation generation = new Generation(); // 当有parties个线程到达barrier,就会更新换代
  private int count; // 记录当前线程数量

(1)构造CyclicBarrier 时设置等待线程总数量parties 和 达到等待线程数量后执行的线程barrierCommand;

(2)线程中调用CyclicBarrier 的await() 方法时,将线程park() 并放入trip 的条件队列中,记录当前阻塞线程数 count;

(3)线程中调用CyclicBarrier 的await() 方法时,发现当前阻塞线程数 count达到了 构造时设置的总线程数,做如下操作:

    ① trip.signalAll()唤醒所有线程

    ② 重置count(从而实现同一个CyclicBarrier 对象可以循环使用)

    ③ 执行barrierCommand线程

一、应用举例

public class CyclicBarrierTest {
private static CyclicBarrier cyclicBarrier; static class CyclicBarrierThread extends Thread {
public void run() {
System.out.println(Thread.currentThread().getName() + "到了");
try {
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("人到齐了,开会吧....");
}
}); for (int i = 0; i < 5; i++) {
new CyclicBarrierThread().start();
}
}
}

二、类结构

public class CyclicBarrier {
private static class Generation { // 内部类,当有parties个线程到达barrier,就会更新换代
boolean broken = false; // 是否损坏
}
private final ReentrantLock lock = new ReentrantLock(); // 重入锁
private final Condition trip = lock.newCondition();
private final int parties; // 等待线程总数量
private final Runnable barrierCommand; // 达到等待线程数量后执行的线程
private Generation generation = new Generation(); // 当有parties个线程到达barrier,就会更新换代
private int count; // 记录当前线程数量 public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
} public CyclicBarrier(int parties) {
this(parties, null);
}
}

三、原理解析

    public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
} private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException(); if (Thread.interrupted()) {
breakBarrier(); // 代失效,唤醒所有线程
throw new InterruptedException();
} int index = --count; // 计数
if (index == 0) { // 达到要求数量
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run(); // 达到等待线程数量后执行barrierCommand
ranAction = true;
nextGeneration(); // 唤醒本代所有线程,生成新一代,重置count
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
} // 线程数量未达到要求数量,将线程挂起等待
for (;;) {
try {
if (!timed)
trip.await(); // 将线程加入condition队列挂起
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && !g.broken) {
breakBarrier();
throw ie;
} else {
Thread.currentThread().interrupt();
}
} // 特殊情况处理
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
} // 代失效,唤醒所有线程
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
} // 唤醒本代所有线程,生成新一代,重置count
private void nextGeneration() {
trip.signalAll();
count = parties;
generation = new Generation();
}

并发工具类(二)同步屏障CyclicBarrier

【死磕Java并发】—–J.U.C之并发工具类:CyclicBarrier

Java并发(十三):并发工具类——同步屏障CyclicBarrier的更多相关文章

  1. Java中的并发工具类(CountDownLatch、CyclicBarrier、Semaphore、Exchanger)

    在JDK的并发包里提供了很多有意思的并发工具类.CountDownLatch.CyclicBarrier和Semaphore 工具类提供了一种并发流程控制的手段,Exchanger 工具类则提供了在线 ...

  2. Redis 工具类 java 实现的redis 工具类

    最近了解了一下非关系型数据库 redis 会使用简单的命令 在自己本地电脑 使用时必须先启动服务器端 在启动客户端 redis 简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内 ...

  3. Rhino+envjs-1.2.js 在java运行网站js 工具类

    java爬虫遇到个页面加密的东西,找了些资料学习学习 做了个java运行js的工具类,希望对大家有用,其中用到client(获取js)可以自行换成自己的client.主要是用了 Rhino就是Java ...

  4. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  5. Java学习-041-颜色工具类(RGB,HEX)

    在日常的网页开发中,经常需要进行颜色数值获取.转换,例如获取红色,获取蓝色,获取绿色,RGB转十六进制颜色,十六进制颜色转RGB等,因而在学习过程中,写了一个小工具类,仅供各位小主参考! 多不闲言,直 ...

  6. JAVA中封装JSONUtils工具类及使用

    在JAVA中用json-lib-2.3-jdk15.jar包中提供了JSONObject和JSONArray基类,用于JSON的序列化和反序列化的操作.但是我们更习惯将其进一步封装,达到更好的重用. ...

  7. JAVA自动生成正则表达式工具类

    经过很久的努力,终于完成了JAVA自动生成正则表达式工具类.还记得之前需要正则,老是从网上找吗?找了想修改也不会修改.现在不用再为此烦恼了,使用此生成类轻松搞定所有正则表达式.赶快在同事面前炫一下吧. ...

  8. java 二进制数字符串转换工具类

    java 二进制数字符串转换工具类 将二进制转换成八进制 将二进制转换成十进制 将二进制转换成十六进制 将十进制转换成二进制 package com.iteye.injavawetrust.ad; i ...

  9. Java学习-049-正则工具类

    自去年九月份决定再次入学和职业资格进阶,开始备战二者考试至今,以及当下进行中的职称申请,犹如孤独的狼,不断前行在路上,而今凡凡总总的已历8月... 不感慨了,如下为一园友需要的正则工具类,直接上码: ...

随机推荐

  1. hash(2018年CSUST省赛选拔赛第一场B题+hash+字典树)

    题目链接:http://csustacm.com:4803/problem/1006 题目: 思路:正如题目一样,本题是一个hash,比赛的时候用的字典树,但是不知道为什么一直RE(听学长说要动态开点 ...

  2. TinyOS在ubuntu 14.04下安装教程

    1:打开/etc/apt/sources.list 文件,在文件最底部添加安装源: deb http://tinyos.stanford.edu/tinyos/dists/ubuntu lucid m ...

  3. C++ STL标准入门

    C++:STL标准入门汇总 第一部分:(参考百度百科) 一.STL简介 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.它是由Alexand ...

  4. perl6正则 3: 行开头与结尾与多行开头,多行结尾

    ^ $ 匹配一行的开头或结尾, 可以用 ^ 或 $. > so 'abcde' ~~ /e$/ True > so 'abcdef' ~~ /e$/ False > so 'abcd ...

  5. 47、求1+2+3+...+n

    一.题目 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 二.解法 public class Solut ...

  6. python 之ConfigParser模块学习

    1.1 读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该secti ...

  7. php 全文搜索解决方法

    全套解决方案 xunsearch 一.安装编译工具 yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-dev ...

  8. 8.Python3标准库--数据持久存储与交换

    ''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...

  9. java关键字(详解)

    目录 1. 基本类型 1) boolean 布尔型 2) byte 字节型 3) char 字符型 4) double 双精度 5) float 浮点 6) int 整型 7) long 长整型 8) ...

  10. gm(GraphicsMagick)图片中文水印乱码问题

    1.GraphicsMagick图片中文水印乱码问题处理方式 如出现乱码是由于服务器中缺少中文字库所致,为避免系统中存在多个中文字库冲突, 所以没有必要在安装GraphicsMagick时就将字库文件 ...