1、什么是fork/join framework?
java 1.7开始提供了fork/join framework,目的是为了使用所有可用的cpu去完成一个任务(通过分治)。
fork:将一个大任务分割成许多小任务
join:将小任务的结果join起来,形成一个结果
2、ForkJoinPool
ForkJoinPool是fork/join framework的核心,它是ExcutorService的实现。
每一条线程在同一时刻只能执行一个任务,ForkJoinPool不会产生线程去执行任务,
2.1如何初始化ForkJoinPool
ForkJoinPool pool = new Fork(3);//最大并发数为3
ForkJoinPool commonPool = ForkJoinPool.commonPool();
2.2 Work Stealing Alogrithm
线程所使用的队列是:double end queue
默认情况下,一个线程会冲它的队列的头部拿出任务,但是当自己的任务执行完成时,他会从其它线程的尾部取,这样子能减少资源竞争问题。
2.3 如何完成一个实例
1、任务类需要继承RecursiveTask或者RecursiveAction,区别是前者每个子任务都有返回值。
2、实现compute()方法,执行任务的代码就写在compute()里面。
3、使用invokeAll(RecursiveTask task)来调用子任务,subTask.join()来执行子任务,得到结果。
3、fork/join应用
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class SumTask extends RecursiveTask<Long> {
private int start;
private int end;
private int[] arr;
private int threshold = 5;
public SumTask(int start, int end, int[] arr) {
this.start = start;
this.end = end;
this.arr = arr;
}
@Override
protected Long compute() {
if(end - start > threshold) {
int mid = (start + end) / 2;
SumTask subTask1 = new SumTask(start, mid, arr);
SumTask subTask2 = new SumTask(mid, end, arr);
invokeAll(subTask1, subTask2); //fork
long subResult1 = subTask1.join();
long subResult2 = subTask2.join();
System.out.println(String.format("compute %d~%d = %d", start, end, subResult1 + subResult2));
return subResult1 + subResult2;
} else {
long sum = 0;
for(int i = start; i < end; i++) {
sum += arr[i];
}
System.out.println(String.format("compute %d~%d = %d", start, end, sum));
return sum;
}
}
public static void main(String[] args) {
int[] arr = new int[100];
for(int i = 0; i < 100; i++) {
arr[i] = i;
}
ForkJoinPool pool = new ForkJoinPool(4);//最大并发数
ForkJoinTask<Long> task = new SumTask(0, 100, arr);
System.out.println("result:" + pool.invoke(task));
}
}