上一节说了CountDown的使用方法,对于用来同步多个线程之间的协作关系,Java更提供了更加高级的方法来实
现,这个类就是CyclicBarrier。 它可以实现当多个分支线程完成他们的工作后,调用await方法来等待,然后等所有的分
支线程工作完毕后,会自动的调用主线程的run方法,这个主线程是一个实现runnable接口的类,在CyclicBarrier实例化
的时候就调用了。
下面我们就用代码来说明这个问题。代码实现的效果是从一个二维数组中查询到我们需要的数字,然后分支成五个
线程来分别从不同的起点开始计算,然后最后调用grouper线程来归并计算的结果得到最终结果。
package com.bird.concursey.charpet4; import java.util.Random; /** * This class will generate a random matrix of numbers between one and 10 where the threads are going to look for a number. * @author bird * 2014年9月22日 上午9:43:49 */ public class MatrixMock { private int data[][]; /** * Fill the matrix with random numbers. Each time you generate a number, compare it with the number you are going to look for. If they are equal, increment the counter. * @param size * @param length * @param number */ 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.printf("Mock: There are %d ocurrences of number in generated data.\n",counter,number); } /** * This method receives an int parameter with the number of a row in the matrix and returns the row if it exists, and returns null if it doesn't exist. * @param row * @return */ public int[] getRow(int row) { if(row > 0 && row > data.length) { return data[row]; } return null; } }
package com.bird.concursey.charpet4; /** * Results. This class will store, in an array, the number of occurrences of the searched number in each row of the matrix. * @author bird * 2014年9月22日 上午9:52:05 */ public class Results { private int[] data; public Results(int size) { data = new int[size]; } /** * This method receives a position in the array and a value as parameters, and establishes the value of that position in the array. * @param position * @param value */ public void setData(int position, int value) { data[position] = value; } public int[] getData() { return data; } }
package com.bird.concursey.charpet4; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class Searcher implements Runnable { private int firstRow; private int lastRow; private MatrixMock mock; private Results results; private int number; private CyclicBarrier cycliBarrier; public Searcher(int firstRow, int lastRow, MatrixMock mock, Results results, int number, CyclicBarrier cycliBarrier) { super(); this.firstRow = firstRow; this.lastRow = lastRow; this.mock = mock; this.results = results; this.number = number; this.cycliBarrier = cycliBarrier; } @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++; } } results.setData(i, counter); } System.out.printf("%s: Lines processed.\n",Thread.currentThread().getName()); try { cycliBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }
package com.bird.concursey.charpet4; import java.util.concurrent.CyclicBarrier; public class Grouper implements Runnable { private Results results; public Grouper(Results results) { super(); this.results = results; } @Override public void run() { int finalResult = 0; System.out.printf("Grouper: Processing results...\n"); int data[] = results.getData(); for (int number : data) { finalResult += number; } System.out.printf("Grouper: Total result: %d.\n", finalResult); } public static void main(String[] args) { final int ROWS=10000; final int NUMBERS=1000; final int SEARCH=5; final int PARTICIPANTS=5; final int LINES_PARTICIPANT=2000; MatrixMock mock = new MatrixMock(ROWS, NUMBERS, SEARCH); Results result = new Results(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.printf("Main: The main thread has finished.\n"); } }