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

CyclicBarrier 支持一个可选的 Runnable命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。

示例用法:下面是一个在并行分解设计中使用 barrier 的例子:

class Solver {
final int N;
final float[][] data;
final CyclicBarrier barrier; class Worker implements Runnable {
int myRow;
Worker(int row) {
myRow = row;
}
public void run() {
while (!done()) {
processRow(myRow);
try {
barrier.await();
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
}
public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
barrier = new CyclicBarrier(N, new Runnable() {
public void run() {
//mergeRows(...);合并结果
}
});
for (int i = 0; i < N; ++i)
new Thread(new Worker(i)).start();
waitUntilDone();
}
}

在这个例子中,每个 worker 线程处理矩阵的一行,在处理完所有的行之前,该线程将一直在屏障处等待。处理完所有的行之后,将执行所提供的Runnable屏障操作,并合并这些行。如果合并者确定已经找到了一个解决方案,那么 done() 将返回 true,所有的 worker 线程都将终止。

如果屏障操作在执行时不依赖于正挂起的线程,则线程组中的任何线程在获得释放时都能执行该操作。为方便此操作,每次调用 await() 都将返回能到达屏障处的线程的索引。然后,您可以选择哪个线程应该执行屏障操作,例如:

 if (barrier.await() == 0) {
// log the completion of this iteration
}

对于失败的同步尝试,CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么在该屏障点等待的其他所有线程也将通过 BrokenBarrierException(如果它们几乎同时被中断,则用 InterruptedException)以反常的方式离开。

内存一致性效果:线程中调用 await() 之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次 happen-before 紧跟在从另一个线程中对应 await() 成功返回的操作。

实现一个矩阵,在矩阵中查找需要查找数字的出现次数。

public class MatrixMock {
private int data[][];
public MatrixMock(int size,int length,int number){
int counter=0;
data=new int[size][length];
Random random=new Random();
for (int i = 0;i <size;i++) {
for (int j=0; j<length; j++) {
data[i][j]=random.nextInt(10);
if(data[i][j]==number){
counter++;
}
}
}
System.out.println("Mock:There are:"+counter+" number in generated data");
}
public int[] getRow(int row){
if(row>=0&&row<data.length){
return data[row];
}
return null;
}
}
//存放矩阵每行的查找结果
public class Result {
private int data[];
public Result(int size) {
data=new int[size];
}
public void setData(int postion,int value){
data[postion]=value;
}
public int[] getData(){
return data;
}
}
//查找线程
public class Searcher implements Runnable {
private int fristRow;//起始行
private int lastRow;//终止行
private MatrixMock matrixMock;//要查找的矩阵
private Result results;//保存查找结果
private int number;//需要查找到数字
private final CyclicBarrier barrier;
public Searcher(int fristRow, int lastRow, MatrixMock matrixMock,
Result results, int number, CyclicBarrier barrier) {
this.fristRow = fristRow;
this.lastRow = lastRow;
this.matrixMock = matrixMock;
this.results = results;
this.number = number;
this.barrier = barrier;
}
@Override
public void run() {
int counter;
System.out.println(Thread.currentThread().getName()
+ ": Processing lines from " + fristRow + " to " + lastRow);
for (int i=fristRow; i<lastRow;i++) {
int row[]=matrixMock.getRow(i);
counter=0;
for (int j = 0; j <row.length; j++) {
if(row[j]==number){
counter++;
}
}
results.setData(i, counter);
}
System.out.println(Thread.currentThread().getName()+":Lines processed");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e){
e.printStackTrace();
}
}
}
//合并查找结果
public class Grouper implements Runnable {
private Result result;
public Grouper(Result result) {
this.result = result;
}
@Override
public void run() {
int finalResult=0;
System.out.println("Grouper: Processing results...");
int data[]=result.getData();
for (int i : data) {
finalResult+=i;
}
System.out.println("Grouper: Total result:"+finalResult);
}
}
public class GrouperMain {
public static void main(String[] args) {
final int ROWS = 10000;
final int NUMBRES = 1000;
final int SEARCH = 5;
final int PARTICIPANTS = 5;
final int LINES_PARTICIPANT = 2000;
MatrixMock mock = new MatrixMock(ROWS, NUMBRES, SEARCH);
Result result = new Result(ROWS);
Grouper grouper = new Grouper(result);
CyclicBarrier barrier = new CyclicBarrier(PARTICIPANTS, grouper);
Searcher searchers[] = new Searcher[PARTICIPANTS];
for (int i = 0; i < PARTICIPANTS; i++) {
searchers[i] = new Searcher(i * LINES_PARTICIPANT, i
* LINES_PARTICIPANT + LINES_PARTICIPANT, mock, result, 5,
barrier);
Thread thread = new Thread(searchers[i]);
thread.start();
}
System.out.println("Main: The Main Thread has finnished");
}
}

运行结果:

Mock:There are:1000810 number in generated data
Thread-0: Processing lines from 0 to 2000
Thread-1: Processing lines from 2000 to 4000
Thread-2: Processing lines from 4000 to 6000
Thread-4: Processing lines from 8000 to 10000
Main: The Main Thread has finnished
Thread-3: Processing lines from 6000 to 8000
Thread-3:Lines processed
Thread-1:Lines processed
Thread-2:Lines processed
Thread-4:Lines processed
Thread-0:Lines processed
Grouper: Processing results...
Grouper: Total result:1000810

应用场景:在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。

JAVA CyclicBarrier类详解的更多相关文章

  1. Java String类详解

    Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...

  2. Java 枚举类详解

    1. 枚举类定义 在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象,这种实例有限而且固定的类,在Java里被称为枚举类. 2. 早期实现枚举的方式 public static f ...

  3. java Random类详解

    java Random类位于java.util包下,主要用来生成随机数,本文详解介绍了Random类的用法,希望能帮到大家 Random类 (java.util) Random类中实现的随机算法是伪随 ...

  4. Java Calender 类详解

    一.   如何创建 Calendar 对象 Calendar 是一个抽象类, 无法通过直接实例化得到对象. 因此, Calendar 提供了一个方法 getInstance,来获得一个Calendar ...

  5. JAVA - 大数类详解

    写在前面 对于ACMer来说,java语言最大的优势就是BigInteger,Bigdecimal,String三个类. 这三个类分别是高精度整数,高精度浮点数和字符串,之所以说这个是它的优势是因为j ...

  6. Java 枚举类 详解

    1.枚举是什么? Java中的枚举其实是一种语法糖,在 JDK 1.5之后出现,用来表示固定且有限个的对象.比如一个季节类有春.夏.秋.冬四个对象:一个星期有星期一到星期日七个对象.这些明显都是固定的 ...

  7. Java重要类详解之ArrayList类

    https://blog.csdn.net/shengmingqijiquan/article/details/52634640 一.ArrayList概述 ArrayList 是一个数组队列,相当于 ...

  8. 【RTTI】java Class类详解

    RTTI (Run-Time Type Information)运行时类信息 Java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息,下面我们来了解一下有关j ...

  9. Java常用类详解

    目录 1. String类 1.1 String的特性 1.2 String字面量赋值的内存理解 1.3 String new方式赋值的内存理解 1.4 String 拼接字面量和变量的方式赋值 1. ...

随机推荐

  1. PMP和PRINCE2的价值各是什么?PRINCE2的含金量如何?PMP和prince2有什么区别?

    很多学员朋友会问我同样的问题:"PMP和PRINCE2到底有什么区别?哪个含金量更高?"看来,这是所有要参加认证的朋友普遍关心的问题,我将根据自己的切身体会,从三个方面回答这个问题 ...

  2. Django后台设置--遇到的问题与解决方案

    1. 后台如何管理项目中的models 新建的Django工程会自动引用admin 应用,新建后台可以通过 createsuperuser 命令建立后台admin超级管理员,我遇到的第一个问题,就是如 ...

  3. IOS开发创建开发证书及发布App应用(九)——等待审核(审核几种状态)

    以下是App应用的几种状态,如果看不到英文,建议复制到网站翻译一下就行,意思差不多能明白的 以上整套流程是在2013年写的,可能有些地方已经不太一样了,只是给大家做一下参考,毕竟再怎么改大概流程还是差 ...

  4. iOS最好用的引导页

    最近项目结束的时候又要改引导页,之前写的启动页改起来太麻烦了,所以就直接封装一个,功能可能还不是很完善,但是感觉用起来也比较方便,在这里和大家分享一下. 这是github的下载地址:https://g ...

  5. Intellj IDEA 简易教程

    Intellj IDEA 简易教程 目录 JDK 安装测试 IDEA 安装测试 调试 单元测试 重构 Git Android 其他 参考资料 Java开发IDE(Integrated Developm ...

  6. 手机自动化测试:appium源码分析之bootstrap八

    手机自动化测试:appium源码分析之bootstrap八   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣, ...

  7. Mybatis基础学习(五)—缓存

    一.概述      mybatis提供查询缓存,如果缓存中有数据就不用从数据库中获取,用于减轻数据压力,提高系统性能.           一级缓存是SqlSession级别的缓存.在操作数据库时需要 ...

  8. java 基础知识四 流程控制

    java   基础知识四 流程控制 Java流程控制包括顺序控制.条件控制和循环控制 顺序控制就是逐条执行 有if和switch两个分支 循环控制就是 又称为回路控制,根据循环初始条件和终结要求,执行 ...

  9. 原生JavaScript实现焦点图轮播

    不管是高校的网站还是电商的页面,焦点图的切换和轮播应该是一项不可或缺的应用.今天把焦点图轮播制作的技术要点做下笔记,以供日后查看. 一.结构层(HTML) 焦点图的HTML结构很简单,就是一个父容器( ...

  10. windows升级到1607后操作很卡顿的解决办法

    CPU I5,固态128G,win7主系统,WIN10和WIN7都安装在固态硬盘上. 未升级之前,操作很流畅,以至于把家里的老古董电脑也换固态,系统换WIN10了.自从升级了1607后这个问题就出现了 ...