博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA CyclicBarrier类详解
阅读量:6904 次
发布时间:2019-06-27

本文共 4977 字,大约阅读时间需要 16 分钟。

 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (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 线程都将终止。

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

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

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

内存一致性效果:线程中调用 await() 之前的操作 那些是屏障操作的一部份的操作,后者依次 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 
=0&&row
//存放矩阵每行的查找结果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
//合并查找结果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 dataThread-0: Processing lines from 0 to 2000Thread-1: Processing lines from 2000 to 4000Thread-2: Processing lines from 4000 to 6000Thread-4: Processing lines from 8000 to 10000Main: The Main Thread has finnishedThread-3: Processing lines from 6000 to 8000Thread-3:Lines processedThread-1:Lines processedThread-2:Lines processedThread-4:Lines processedThread-0:Lines processedGrouper: Processing results...Grouper: Total result:1000810

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

转载地址:http://krldl.baihongyu.com/

你可能感兴趣的文章
[学习笔记]博弈论
查看>>
python os sys模块(二)
查看>>
一次linux启动故障记录
查看>>
Innodb间隙锁,细节讲解(转)
查看>>
Apache安装
查看>>
关于对char类型数据赋予负值的汇编表现
查看>>
C语言结构体在内存中的存储情况探究------内存对齐
查看>>
win10安装MarkdownPad 2报错This view has crashed的处理及md简单语法
查看>>
Windows聚焦转为图片
查看>>
POJ NOI0101-09 字符菱形
查看>>
Scala 学习笔记之函数(3)
查看>>
[转载] 信息系统项目管理师考试习题——整体管理
查看>>
LC 425 word squares
查看>>
Web框架之Django_08 重要组件(form组件、cookie和session组件)
查看>>
HDU 6103
查看>>
zookeeper 实现分布式锁
查看>>
sql server 数据修改不了的设计
查看>>
Reinforcement Learning by Sutton 第三章习题答案
查看>>
mysql tinyint
查看>>
UNIX网络编程——getsockname和getpeername函数
查看>>