ForkJoinPool 是 Java 7 中引入的并发库类。它通常是以递归的方式运行,采用分治思想将大任务分割成几个小任务,小任务继续分割成更小的任务,直至任务不可分割,然后运行这些任务。因此,ForkJoinPool 的适用范围不大,仅限于某任务能被分解成多个子任务,且这些子任务运行的结果可以合并成最终结果。
ForkJoinPool 中实现了一种工作窃取算法,所谓工作窃取指的是闲置线程的任务队列空了,就从其他忙碌线程中的任务队列中处理任务。
ForkJoinPool 的运行模式如下:
提交到 ForkJoinPool 的任务,必须是 RecursiveTask 或者 RecursiveAction 的子类,它们都是一个抽象类,且继承与 ForkJoinTask。类中 compute() 方法是执行 RecursiveTask 的主要方法。区别在于:RecursiveTask 代表有返回值的任务,RecursiveAction 代表没有返回值的任务。
看一段示例代码,使用 Fork/Join 模式实现斐波那契数列。
public class Main {
public static void main(String[] args) throws Exception {
ForkJoinTask<Integer> fjt = new Fibonacci(10);
ForkJoinPool fjpool = new ForkJoinPool();//默认按照CPU核数来创建线程数量。
Future<Integer> result = fjpool.submit(fjt);
System.out.println(result.get());
}
}
class Fibonacci extends RecursiveTask<Integer> {
final int n;
Fibonacci(int n) {
this.n = n;
}
@Override
public Integer compute() {
if (n == 1||n == 2) {
return 1;
}
Fibonacci f1 = new Fibonacci(n - 1);
Fibonacci f2 = new Fibonacci(n - 2);
f1.fork();
f2.fork();
return f1.join() + f2.join();
}
}
代码说明:
Fibonacci 类是 RecursiveTask 泛型的子类,重写了 compute 方法。当 f1.fork() 和 f2.fork() 运行的时候,就相当于重新开了 1 个线程来异步计算一个子任务。而 f1.join() 和 f2.join() 方法都是阻塞当前线程,f1 和 f2 的结果计算出来后就返回结果。代码中通过 fork 方法,递归的运行 compute 方法,不断的使用异步线程去计算结果。
在 Main 方法中,ForkJoinPool 中提交了 Fibonacci 类的实例。因此可以通过 ForkJoinPool 线程池中的线程完成计算。
上述代码只是一个用法演示,并不意味着用这种方式计算斐波那契数列是高效的。