(三)线程同步工具集_4---在一个约定点同步任务
来源:互联网 发布:爱尔兰和北爱尔兰 知乎 编辑:程序博客网 时间:2024/06/05 15:10
在一个约定点同步任务(Synchronizing tasks in a common point)
Java 并发API中提供了一个同步工具CyclicBarrier类可以使多个线程在约定点进行任务同步,该类和CountDownLatch类有点类似,CountDownLatch是等待多个并发事件,在上节有解释;
CyclicBarrier类初始化有两个参数,第一个是要同步的线程个数,第二个要同步的任务(该参数实现了Runnable接口);当这些要同步的线程到达到了这个约定的同步点,它将调用await()方法进入睡眠状态,当所有要同步的线程都到达了这个约定的点后,CyclicBarrier将会唤醒所有睡眠的这些线程,然后执行要同步的任务(传入的第二个参数);
CyclicBarrier最好的就是它可以传入一个实现了Runnable接口的对象,在所有线程到达约定点后,在执行这个对象;这个特性非常适合分治算法 的思想;
再接下来的例子中,简单的使用CyclicBarrier模拟一个简单的分治算法;
问题:即模拟一个矩阵,从该矩阵中查找一个给定的数,并统计该数值在该矩阵中出现的次数;
解决思路:
开启多个线程,每个线程负责查找若干行,并把每一行该数值出现的次数放置到一个数组中,作为结果,每行对应与该数组的索引;在所有线程都查找完成后,执行同步任务,这里仅仅简单的输出最终的结果;
动手实现
1.辅助类,用来模拟矩阵
public class MatrixMock { private int data[][]; public MatrixMock(int rows,int cols,int number){ int counter=0; data=new int[rows][cols]; Random random=new Random(); for (int i = 0; i < rows; i++) { for(int j=0;j<cols;j++){ data[i][j]=random.nextInt(10); if (data[i][j] == number) { counter++; } } } System.out.printf("Mock: There are %d occurrence of %d in generated data.\n",counter,number); } public int[] getRow(int row) { if ((row >= 0) && (row < data.length)) { return data[row]; } return null; }}2.辅助类,用来放置每个线程处理结果,索引对应矩阵行数,列对应每行查找到指定数值的次数
public class Result { private int data[]; public Result(int size) { this.data = new int[size]; } public void setData(int position,int value){ data[position]=value; } public int[] getData(){ return data; }}
3.用来执行计算的线程
public class Searcher implements Runnable { private int firstRow; private int lastRow; private MatrixMock mock; private Result result; private int number; private final CyclicBarrier barrier; public Searcher(int firstRow, int lastRow, MatrixMock mock, Result result, int number, CyclicBarrier barrier) { this.firstRow = firstRow; this.lastRow = lastRow; this.mock = mock; this.result = result; this.number = number; this.barrier = barrier; } @Override public void run() { int counter; System.out.printf("%s: Processing lines from %d to %d.\n", Thread.currentThread().getName(), firstRow, lastRow); for (int i = firstRow; i < lastRow; i++) { int row[] = mock.getRow(i); counter = 0; for (int j = 0; j < row.length; j++) { if (row[j] == number) { counter++; } } result.setData(i, counter); } System.out.printf("%s: Lines processed.\n", Thread.currentThread().getName()); try { barrier.await(); } catch (BrokenBarrierException | InterruptedException e) { e.printStackTrace(); } }}4.同步任务,当所有线程完成之后执行,类似于分治算法中的结果合并;
public class Grouper implements Runnable { private Result result; public Grouper(Result result) { this.result = result; } @Override public void run() { int finalResult=0; System.out.printf("Grouper: Processing results...\n"); int data[]=result.getData(); for(int number:data){ finalResult+=number; } System.out.printf("Grouper: Total result: %d.\n",finalResult); }}
5.Main
public class Main { public static void main(String[] args) { final int rows=10000; final int cols=1000; final int search=5; final int participants=5; final int linesParticipant=2000; MatrixMock mock=new MatrixMock(rows, cols,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++){ // Every searching thread searches 2000 rows searchers[i]=new Searcher(i*linesParticipant, (i*linesParticipant) + linesParticipant, mock, result, 5,barrier); Thread thread=new Thread(searchers[i]); thread.start(); } System.out.printf("Main: The main thread has finished.\n"); }}一次运行结果:
Mock: There are 1001252 occurrence of 5 in generated data.
Main: The main thread has finished.
Thread-0: Processing lines from 0 to 2000.
Thread-4: Processing lines from 8000 to 10000.
Thread-1: Processing lines from 2000 to 4000.
Thread-3: Processing lines from 6000 to 8000.
Thread-2: Processing lines from 4000 to 6000.
Thread-1: Lines processed.
Thread-3: Lines processed.
Thread-2: Lines processed.
Thread-0: Lines processed.
Thread-4: Lines processed.
Grouper: Processing results...
Grouper: Total result: 1001252.
要点
1.CyclicBarrier还提供了getNumberWaiting()方法,用来获取当前被阻塞的线程个数;
2.利用该类执行分治任务是一个很不错的选择;
- (三)线程同步工具集_4---在一个约定点同步任务
- (三)线程同步工具集_1---控制线程并发访问一个资源
- (二)线程同步_4---使用Lock同步代码块
- 任务,线程和同步(三)之取消架构
- JDK5新特性之线程同步工具类(三)
- OpenMP(三) 线程同步
- Java线程同步(三)
- 线程同步(面试三)
- (三)线程同步工具集_2---控制并发访问资源的多个副本
- (三)线程同步工具集_3---等待多个并发事件
- 任务线程和同步(一、Parallel)
- 任务线程和同步(二、Task)
- CyclicBarrier线程同步工具
- 线程同步工具类
- 线程同步工具类
- 线程间同步工具
- 线程同步工具-Semaphore
- 线程同步工具-CountDownLatch
- 初识c指针练习-- 检索进程中是否存在qq运行
- 树状数组
- 小马哥-----高仿红米note A6主板 拆机主板图与开机图 新版高仿版本出现市场 警惕
- hdu 2120 Ice_cream's world I(判断是否有环,简单的并查集)
- 3D动态锁屏+3D动态壁纸,完美整合到一起!
- (三)线程同步工具集_4---在一个约定点同步任务
- HDU 2079-选课时间(母函数)
- Combination Sum I, II
- android 自定义ListView 使其带单选框按钮,并解决item点击不响应的问题
- ThinkPad
- R语言学习——向量矩阵
- ListView 中添加按钮,动态删除添加ItemView的操作
- 字典树(trie树)、后缀树
- 时间复杂度与空间复杂度