ForkJoinPool是ExecutorService的实现类,也是一种特殊的线程池。它提供了如下两个常用的构造器:
- ForkJoinPool(int parallelism):创建一个包含parallelism个并行线程的ForkJoinPool。
- ForkJoinPool():以Runtime.availableProcessors()方法的返回值作为parallelism参数来创建ForkJoinPool。
在java8进一步丰富了ForkJoinPool的功能,为其增加了通用池功能。通过如下两个静态方法提供通用池的功能:
- ForkJoinPool commonPool():该方法返回一个通用池,通用池的运行状态不会受shutdown()或shutdownNow()方法的影响。
- int getCommonPoolParallelism():该方法返回通用池的并行级别。
创建ForkJoinPool后就可以调用submit(ForkJoinTask task) 或 invoke(ForkJoinTask task)方法来执行指定任务了。其中ForkJoinTask代表一个可以并行、合并的任务。
ForkJoinTask是一个抽象类,它还有两个抽象子类:RecursiveAction和RecursiveTask。
其中RecursiveAction代表没有返回值的任务,例如:
public class PrintTask extends RecursiveAction {
//每个"小任务"最多打印50次
private static final int THRESHOLD = 50;
private int start;
private int end;
public PrintTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
//当end与start之间的差值小于THRESHOLD时开始打印
if (end - start < THRESHOLD){
for(int i = start; i < end; i++) {
System.out.println(Thread.currentThread().getName() + " 的i值:" + i);
}
} else {
//当end与start之间当差值大于THRESHOLD时进行任务拆解
int middle = (start + end) >> 1;
PrintTask left = new PrintTask(start, middle);
PrintTask right = new PrintTask(middle, end);
//并行执行两个"小任务"
left.fork();
right.fork();
}
}
public static void main(String[] args) throws Exception{
ForkJoinPool pool = new ForkJoinPool();
//提交可分解当PrintTask任务
pool.submit(new PrintTask(0,400));
pool.awaitTermination(2, TimeUnit.SECONDS);
//关闭线程池
pool.shutdown();
}
}
RecursiveTask代表有返回值的任务,例如:
public class CalTask extends RecursiveTask<Integer> {
//每个"小任务"最多累加50次
private static final int THRESHOLD = 50;
private int arr[];
private int start;
private int end;
public CalTask(int[] arr, int start, int end) {
this.arr = arr;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
//当end与start之间的差值小于THRESHOLD时开始累加计算
if (end - start < THRESHOLD){
for (int i = start; i < end; i++){
sum += arr[i];
}
return sum;
} else {
int middle = (start + end) >> 1;
CalTask left = new CalTask(arr, start,middle);
CalTask right = new CalTask(arr, middle, end);
left.fork();
right.fork();
return left.join()+right.join();
}
}
public static void main(String[] args) throws Exception{
int[] arr = new int[200];
Random random = new Random();
int total = 0;
//初始化数组
for (int i = 0; i < arr.length; i++){
int tmp = random.nextInt(20);
total += (arr[i] = tmp);
}
System.out.println("total = " + total);
//创建一个通用池
ForkJoinPool pool = ForkJoinPool.commonPool();
//提交可分解的Caltask任务
Future<Integer> future = pool.submit(new CalTask(arr, 0, arr.length));
System.out.println(future.get());
//关闭线程池
pool.shutdown();
}
}