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

16-案例实现

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

案例实现

根据如下步骤来实现本案例。

1.创建一个名为 Task 的类。声明并继承 RecursiveTask 类,泛型为 Integer 类:

public class Task extends RecursiveTask<Integer> {

2.声明一个名为 array 的私有 int 数组变量—用来模拟本例中将要处理的数组数据:

private int array[];

3.声明两个名为 startend 的私有 int 变量,这些变量将决定任务处理数组中的哪些数据:

private int start, end;

4.实现该类的构造方法并初始化全部属性:

public Task(int array[], int start, int end){
  this.array=array;
  this.start=start;
  this.end=end;
}

5.实现任务的 compute() 方法。因为 RecursiveTask 类的泛型为 Integer 类,所以该方法必须返回一个 Integer 型实例对象。首先,在控制台打印 startend 的信息:

@Override
protected Integer compute() {
  System.out.printf("Task: Start from %d to %d\n",start,end);

6.如果 startend 所决定的待处理的元素个数小于 10 ,则检查这批元素是否处于数组的前4个位置,如果符合要求,则抛出 RuntimeException 异常,否则让任务休眠1s:

if (end-start<10) {
  if ((3>start)&&(3<end)){
    throw new RuntimeException("This task throws an"+
                    "Exception: Task from "+start+" to "+end);
  }
  try {
    TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }

7.否则分割元素块为两部分,创建两个 Task 实例对象来处理这些元素块,并在池中调用 invokeAll() 方法来执行它们:

} else {
  int mid=(end+start)/2;
  Task task1=new Task(array,start,mid);
  Task task2=new Task(array,mid,end);
  invokeAll(task1, task2);
  System.out.printf("Task: Result form %d to %d: %d\n",
                    start,mid,task1.join());
  System.out.printf("Task: Result form %d to %d: %d\n",
                    mid,end,task2.join());
}

8.在控制台打印 startend 变量值,以此表明任务结束:

System.out.printf("Task: End form %d to %d\n",start,end);

9.任务返回 0 作为执行结果:

return 0;

10.至此,我们可以开始实现应用程序的入口,创建包含 main() 方法的 Main 类:

public class Main {
  public static void main(String[] args) {

11.创建一个包含 100 个整数的数组:

int array[]=new int[100];

12.创建一个 Task 实例对象来处理该数组:

Task task=new Task(array,0,100);

13.使用默认的构造方法创建一个 ForkJoinPool 实例对象:

ForkJoinPool pool=new ForkJoinPool();

14.在池中调用 execute() 方法执行任务:

pool.execute(task);

15.调用 shutdown() 方法关闭 ForkJoinPool 类:

pool.shutdown();

16.调用 awaitTermination() 方法来等待任务执行完成。如果不关心任务返回结果的耗时,则传递 1TimeUnit.DAYS 作为参数:

try {
  pool.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
  e.printStackTrace();
}

17.调用 isCompletedAbnormally() 方法检查任务或子任务是否抛出异常。当任务抛出异常时,在控制台打印出相关信息。使用 ForkJoinTask 类中的 getException() 方法获取异常:

if (task.isCompletedAbnormally()) {
  System.out.printf("Main: An exception has ocurred\n");
  System.out.printf("Main: %s\n",task.getException());
}
System.out.printf("Main: Result: %d",task.join());