15-案例实现
案例实现
根据如下步骤实现本案例。
1.先实现两个辅助类,以此作为本案例的开始。创建一个名为 MatrixMock
的类,它将生成一个由0~9的数字组成的随机矩阵,用于让线程从中查找一个数字:
public class MatrixMock {
2.声明一个私有的整型矩阵,并将其命名为 data
:
private final int data[][];
3.实现该类的构造器。它接收矩阵的行数、列数,以及将要查找的数字作为参数,这3个参数都是 int
类型的:
public MatrixMock(int size, int length, int number){
4.在构造器中初始化这些变量:
int counter=0;
data=new int[size][length];
Random random=new Random();
5.用随机数填充矩阵。每生成一个随机数,都要将其与所查找的数字对比一下,如果相等,则计数器的值加1:
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++; }
}
}
}
6.在控制台上打印所要查找的数字在矩阵中出现的次数。这条信息用来验证多线程查找结果是否正确:
System.out.printf("Mock: There are %d occurrences of number in
generated data.\n",counter,number);
7.实现 getRow()
方法。该方法接收一个 int
类型参数,它表示矩阵行号。如果行号存在,则返回该行;如果不存在,则返回 null
:
public int[] getRow(int row){
if ((row>=0)&&(row<data.length)){
return data[row];
}
return null;
}
8.创建一个名为 Results
的类。这个类在一个数组中存放每行找到结果的个数:
public class Results {
9.声明一个私有的名为 data
的 int
类型数组:
private final int data[];
10.实现该类的构造器。它接收一个 int
类型参数,它表示数组的大小:
public Results(int size){
data=new int[size];
}
11.实现 setData()
方法。该方法接收一个表示数组下标的 int
类型参数 position
,一个 int
类型参数 value
。该方法内部将 value
值放到 data
数组对应位置中:
public void setData(int position, int value){
data[position]=value;
}
12.实现 getData()
方法。该方法将返回保存结果的数组:
public int[] getData(){
return data;
}
13.创建完两个辅助类后,开始实现案例线程。创建一个名为 Searcher
的类,并实现 Runnable
接口。该类将搜索矩阵中指定几行中的指定数字:
public class Searcher implements Runnable {
14.声明两个私有的 int
类型属性: firstRow
和 lastRow
。这两个属性用于决定实例对象搜索矩阵的子集范围:
private final int firstRow;
private final int lastRow;
15.声明一个私有的名为 mock
的 MatrixMock
类型的属性:
private final MatrixMock mock;
16.声明一个私有的名为 results
的 Results
类型的属性:
private final Results results;
17.声明一个 私有
的名为 number
的 int
类型的属性,用于存储需要查找的数字:
private final int number;
18.声明一个名为 barrier
的 CyclicBarrier
类型的属性:
private final CyclicBarrier barrier;
19.实现该类的构造器。在构造器中对之前声明的属性进行初始化:
public Searcher(int firstRow, int lastRow, MatrixMock mock,
Results results, int number, CyclicBarrier barrier){
this.firstRow=firstRow;
this.lastRow=lastRow;
this.mock=mock;
this.results=results;
this.number=number;
this.barrier=barrier;
}
20.实现 run()
方法——该方法将实现数字搜索功能。在该方法内部定义一个局部变量 counter
,用来记录每行查找到的次数:
@Override
public void run() {
int counter;
21.将当前线程任务处理的行的范围输出至控制台:
System.out.printf("%s: Processing lines from %d to %d.\n",
Thread.currentThread().getName(),
firstRow,lastRow);
22.处理所有指派给该线程的行。对于每一行,统计被搜索数字出现的次数,并将统计结果存储到 Results
对象相应的位置上:
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);
}
23.向控制台输出信息,用来表明当前线程搜索完毕:
System.out.printf("%s: Lines processed.\n",
Thread.currentThread().getName());
24.调用 CyclicBarrier
对象的 await()
方法,并且添加必要的代码对 Interrupted- Exception
和 BrokenBarrierException
异常进行处理:
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
25.创建一个名为 Grouper
的类,并实现 Runnable
接口,这个类用来汇总矩阵中指定数字出现的次数。该类需要使用存储矩阵每行统计结果的 Results
对象进行汇总:
public class Grouper implements Runnable {
26.声明一个私有的名为 results
的 Results
类型的属性:
private final Results results;
27.实现该类的构造器。在构造器中对 Results
属性进行初始化:
public Grouper(Results results){
this.results=results;
}
28.实现 run()
方法,汇总 results
数组中的统计结果,得到矩阵中指定数字出现的总数:
@Override
public void run() {
29.声明一个 int
类型的变量 finalResult
,并向控制台输出一条信息,用来表明处理开始:
int finalResult=0;
System.out.printf("Grouper: Processing results...\n");
30.通过 results
对象的 getData()
方法得到指定数字在每行出现的次数,然后将所有次数累加到 finalResult
中:
int data[]=results.getData();
for (int number:data){
finalResult+=number;
}
31.在控制台中,输出最后的统计结果:
System.out.printf("Grouper: Total result: %d.\n", finalResult);
32.实现案例程序的入口:
public class Main {
public static void main(String[] args) {
33.声明并初始化5个常量,用于存储应用的参数:
final int ROWS=10000;
final int NUMBERS=1000;
final int SEARCH=5;
final int PARTICIPANTS=5;
final int LINES_PARTICIPANT=2000;
34.创建一个名为 mock
的 MatrixMock
对象。其代表的矩阵大小为10000×10000,需要查找的数字为5:
MatrixMock mock=new MatrixMock(ROWS, NUMBERS,SEARCH);
35.创建一个名为 results
的 Results
对象,其将会存储10000个元素:
Results results=new Results(ROWS);
36.创建一个名为 grouper
的 Grouper
对象:
Grouper grouper=new Grouper(results);
37.创建一个名为 barrier
的 CyclicBarrier
对象,用于等待5个线程。当这5个线程执行完毕后,它会执行之前创建的 Grouper
对象:
CyclicBarrier barrier=new CyclicBarrier(PARTICIPANTS,grouper);
38.创建5个 Searcher
对象和5个线程对象来执行并启动它们:
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, results, 5,barrier);
Thread thread=new Thread(searchers[i]);
thread.start();
}
System.out.printf("Main: The main thread has finished.\n");