当前位置:嗨网首页>书籍在线阅读

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.声明一个私有的名为 dataint 类型数组:

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 类型属性: firstRowlastRow 。这两个属性用于决定实例对象搜索矩阵的子集范围:

private final int firstRow;
private final int lastRow;

15.声明一个私有的名为 mockMatrixMock 类型的属性:

private final MatrixMock mock;

16.声明一个私有的名为 resultsResults 类型的属性:

private final Results results;

17.声明一个 私有 的名为 numberint 类型的属性,用于存储需要查找的数字:

private final int number;

18.声明一个名为 barrierCyclicBarrier 类型的属性:

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- ExceptionBrokenBarrierException 异常进行处理:

try {
  barrier.await();
} catch (InterruptedException e) {
  e.printStackTrace();
} catch (BrokenBarrierException e) {
  e.printStackTrace();
}

25.创建一个名为 Grouper 的类,并实现 Runnable 接口,这个类用来汇总矩阵中指定数字出现的次数。该类需要使用存储矩阵每行统计结果的 Results 对象进行汇总:

public class Grouper implements Runnable {

26.声明一个私有的名为 resultsResults 类型的属性:

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.创建一个名为 mockMatrixMock 对象。其代表的矩阵大小为10000×10000,需要查找的数字为5:

MatrixMock mock=new MatrixMock(ROWS, NUMBERS,SEARCH);

35.创建一个名为 resultsResults 对象,其将会存储10000个元素:

Results results=new Results(ROWS);

36.创建一个名为 grouperGrouper 对象:

Grouper grouper=new Grouper(results);

37.创建一个名为 barrierCyclicBarrier 对象,用于等待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");