Forkjoin
Fork/Join框架继承ExecutorService
接口,帮助我们方便利用多处理器的优点。它专为可以递归分解成小块的工作而设计。目标是使用所有可用的处理能力来提高应用程序的性能。
和所有实现ExecutorService
接口的一样,fork/join框架将任务分配给线程池中的工作线程,不同的是,fork/join框架使用了"工作窃取"算法。比如要完成一个比较大的任务,完全可以把这个任务分割成若干个互不依赖的小任务/子任务。为了方便地管理这些任务,于是把这些子任务分别放到不同的队列里,这时就会出现有的线程会先把自己队列里的任务快速执行完毕,而其他线程对应的队列里还有任务等待处理,完成任务的线程与其等着,不如去帮助其他线程分担要执行的任务,于是它就去其他线程的队列里窃取一个任务来执行。
主要的方法
RecursiveTask例子
/**
* @author donghaibin
* @date 2019-08-17
*/
@RequiredArgsConstructor
public class SumTask extends RecursiveTask<Integer> {
private static final int THRESHOLD = 10;
private final int[] data;
private final int start;
private final int end;
private int sum(int[] data, int start, int end) {
int result = 0;
for (int i = start; i < end; i++) {
result += data[i];
}
return result;
}
@Override
protected Integer compute() {
if (end - start < THRESHOLD) {
return sum(data, start, end);
}
int middle = (start + end) / 2;
SumTask left = new SumTask(data, start, middle);
SumTask right = new SumTask(data, middle, end);
left.fork();
right.fork();
return left.join() + right.join();
}
}
/**
* @author donghaibin
* @date 2019-08-17
*/
public class ForkJoinDemo {
public static void main(String[] args) {
int[] ints = IntStream.rangeClosed(1, 100).toArray();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Integer> task = forkJoinPool.submit(new SumTask(ints, 0, ints.length));
Integer result = task.invoke();
System.out.println(result);
}
}
运行结果:
1050
RecursiveAction和RecursiveTask的区别是没有返回值,在不需要返回数据的时候可以使用RecursiveAction
,ForkJoinPool
继承ExecutorService
用于创建执行线程池,用法基本上和ExectorService
一致。