2.9.集合点同步
来源:互联网 发布:微信淘宝客怎么做 编辑:程序博客网 时间:2024/06/06 08:34
集合点同步
上节讨论了如何实现等待并发线程完成,如果并发线程在一个节点需要等待其他的并发线程完成操作,而后才能继续处理,如何让并发线程能够在一点(这个点称之为集合点)等待其他线程?为更容易的处理这类问题,Java5引入了CyclicBarrier类,它也是一个同步辅助类,允许多个线程在某个点上进行同步。
CyclicBarrier使用一个整数进行初始化,这个数是需要在某点同步的线程数。当一个线程到达指定点后,调用await方法等待其他的线程。当线程调用await方法后,CyclicBarrier类将阻塞这个线程并使之休眠直到所有其他线程到达。当最后一个线程调用CyclicBarrier的await方法时,CyclicBarrier对象将唤醒所有在等待的线程,然后这些线程将继续执行。
重置
CyclicBarrier可以被重置回初始状态,并把它的内部计数器重置为初始化时的值。调用reset方法可以将CyclicBarrier对象重置,重置后在await方法中等待的线程将收到BrokenBarrierException异常,并发程序需要捕获此异常并作现场清理。
损坏
CyclicBarrier有一种特殊状态:损坏(Broken)。当线程在await方法上等待时如果其中一个线程被中断,这个线程抛出InterruptedException其他等待线程将抛出BrokenBarrierException异常,这时CyclicBarrier对象就处于损坏状态。CyclicBarrier的isBorken()方法可以查询是否处于损坏状态。
后处理
CyclicBarrier还有一个特性:可以传入另一个Runnable对象作为初始化参数。当所有的线程都到达集合点后,CyclicBarrier类将这个Runnable对象作为线程执行。这个特性使这个类在并行任务上很类似分治归并编程模型。
这里以查找二维数组中最大值为例来说明CyclicBarrier的作用和用法,简单起见二维数组的每一维都由一个单独线程来查找最大值,等这些线程都找出各自的最大值后,最后由归并线程从各个线程查找出来的结果中再找出最大值。示例代码如下:
public class CyclicBarrierDemo { public static void main(String[] args){ int[][] arrays = new int[4][10]; //初始化二维数组 for(int i=0; i<arrays.length; i++){ for(int j=0;j<arrays[0].length;j++){ int tmp = (int)(Math.random() * 1000); arrays[i][j] = tmp; } } Result result = new Result(); //创建归并器 Grouper grouper = new Grouper(result); CyclicBarrier barrier = new CyclicBarrier(arrays.length,grouper); //创建查找线程,线程数量就是数组一维的数量 System.out.println("main:创建查找线程"); Thread[] searchThreads = new Thread[arrays.length]; for(int i=0; i<arrays.length; i++){ Searcher searcher = new Searcher(arrays[i],result, barrier); searchThreads[i] = new Thread(searcher); } //启动查找线程 System.out.println("main:启动查找线程"); for(int i=0; i<arrays.length; i++){ searchThreads[i].start(); } System.out.println("main:退出"); }}class Searcher implements Runnable{ private Result result; private int[] arrays; private CyclicBarrier barrier; Searcher(int[] arrays, Result result, CyclicBarrier barrier) { this.result = result; this.arrays = arrays; this.barrier = barrier; } @Override public void run() { int max = 0; for(int value : arrays){ if(max < value){ max = value; } } result.add(max); System.out.println("Searcher," + Thread.currentThread().getName() + ":最大数是:" + max); System.out.println("Searcher," + Thread.currentThread().getName() + ":等待其他线程"); try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("Searcher," + Thread.currentThread().getName() + ":退出查找"); }}class Grouper implements Runnable{ Result result; Grouper(Result result) { this.result = result; } @Override public void run() { System.out.println("Grouper:开始归并"); int max = 0; List<Integer> values = result.getAll(); for(int value : values){ if(max < value){ max = value; } } System.out.println("Grouper:最大数是:" + max); System.out.println("Grouper:退出归并"); }}/** 结果保存类 **/class Result{ private List<Integer> result = new ArrayList<Integer>(10); public synchronized void add(int i){ result.add(i); } public List<Integer> getAll(){ return result; }}
程序运行日志:
main:创建查找线程main:启动查找线程main:退出Searcher,Thread-0:最大数是:953Searcher,Thread-0:等待其他线程Searcher,Thread-2:最大数是:963Searcher,Thread-2:等待其他线程Searcher,Thread-3:最大数是:831Searcher,Thread-3:等待其他线程Searcher,Thread-1:最大数是:973Searcher,Thread-1:等待其他线程Grouper:开始归并Grouper:最大数是:973Grouper:退出归并Searcher,Thread-0:退出查找Searcher,Thread-2:退出查找Searcher,Thread-3:退出查找Searcher,Thread-1:退出查找
0 0
- 2.9.集合点同步
- loadrunner的同步点/集合点
- Java并发编程-13-在集合点的同步-CyclicBarrier
- Java7并发编程--3.3、CyclicBarrier在集合点同步
- [笔记][Java7并发编程实战手册]3.5 在集合点的同步CyclicBarrier循环barrier
- java集合点
- Jmeter-集合点
- LoardRunner集合点
- Jmeter集合点
- Loadrunner集合点
- LoadRunner集合点
- LR_集合点
- jmeter 集合点
- JMeter集合点
- jmeter 集合点
- loadrunner插入集合点
- Loadrunner中集合点详解
- LoadRunner常用知识点-----集合点
- OCP-1Z0-051 第76题 INSTR和SUBSTR函数
- VS2010字体颜色背景设置
- OJ 上常见错误提示
- 八皇后问题 DFS
- java异常笔记
- 2.9.集合点同步
- 【JavaScript】JavaScript DOM 编程
- 【裸机开发笔记】6410的系统时钟设置(中)---相关寄存器介绍
- 个人对于java引用的理解
- 简单的排列大小
- Android 外部存储权限分析
- RPC与Socket的关系,RPC与RMI的关系!
- java异常处理
- 【裸机开发笔记】6410的系统时钟设置(下)---几个常用函数的C源码。