继续谈谈Fork/Join框架,今天我们主要看看RecursiveTask的使用方法,以及与之有关的有趣的事情。
例子2 RecursiveTask应用实例
除了 RecursiveAction,Fork/Join 框架还提供了其他 ForkJoinTask 子类:带有返回值的 RecursiveTask。从 RecursiveTask 继承的子类同样需要重载 protected void compute() 方法。与 RecursiveAction 稍有不同的是,它可使用泛型指定一个返回值的类型。下面,我们来看看如何使用 RecursiveTask 的子类。
原文代码:
class Fibonacci extends RecursiveTask<Integer> { final int n; Fibonacci(int n) { this.n = n; } private int compute(int small) { final int[] results = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; return results[small]; } public Integer compute() { if (n <= 10) { return compute(n); } Fibonacci f1 = new Fibonacci(n - 1); Fibonacci f2 = new Fibonacci(n - 2); f1.fork(); f2.fork(); return f1.join() + f2.join(); } public static void main(String... args) throws InterruptedException, ExecutionException { ForkJoinTask<Integer> fjt = new Fibonacci(45); ForkJoinPool fjpool = new ForkJoinPool(); Future<Integer> result = fjpool.submit(fjt); System.out.println(result.get()); } }
Copy到IDE中,上面代码斜体部分,频频亮出红叉,于是翻看API文档,发现API发生一些变化, 具体修改如下:
修改一次后的代码:
package fj; import java.util.concurrent.ExecutionException; import jsr166y.ForkJoinPool; import jsr166y.ForkJoinTask; import jsr166y.RecursiveTask; class Fibonacci extends RecursiveTask<Integer> { final int n; Fibonacci(int n) { this.n = n; } private int compute(int small) { final int[] results = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; return results[small]; } public Integer compute() { if (n <= 10) { return compute(n); } Fibonacci f1 = new Fibonacci(n - 1); Fibonacci f2 = new Fibonacci(n - 2); f1.fork(); f2.fork(); return f1.join() + f2.join(); } public static void main(String... args) throws InterruptedException, ExecutionException { ForkJoinTask<Integer> fjt = new Fibonacci(40); ForkJoinPool fjpool = new ForkJoinPool(); fjpool.execute(fjt); Integer resultInt = fjt.get(); System.out.println(resultInt); } }
总算没有烦人的红叉了,心里暗爽着呢,抓紧按下运行文件……DOWN!
Exception in thread "ForkJoinPool-1-worker-2009" java.lang.OutOfMemoryError: Java heap space at jsr166y.ForkJoinWorkerThread.onStart(ForkJoinWorkerThread.java:345) at jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:310) 生成已停止(总时间:5 秒)
怎么了?怎么会出现这种问题呢?习惯性的翻看RecursiveTask API文档,它也给出同样的例子只是有几句代码不同:
Fibonacci f1 = new Fibonacci(n - 1); f1.fork(); Fibonacci f2 = new Fibonacci(n - 2); return f2.compute() + f1.join();
照葫芦画瓢,再次修改后的代码:
package fj; import java.util.concurrent.ExecutionException; import jsr166y.ForkJoinPool; import jsr166y.ForkJoinTask; import jsr166y.RecursiveTask; class Fibonacci extends RecursiveTask<Integer> { final int n; Fibonacci(int n) { this.n = n; } private int compute(int small) { final int[] results = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; return results[small]; } public Integer compute() { if (n <= 10) { return compute(n); } Fibonacci f1 = new Fibonacci(n - 1); f1.fork(); Fibonacci f2 = new Fibonacci(n - 2); return f2.compute() + f1.join(); } public static void main(String... args) throws InterruptedException, ExecutionException { ForkJoinTask<Integer> fjt = new Fibonacci(40); ForkJoinPool fjpool = new ForkJoinPool(); fjpool.execute(fjt); Integer resultInt = fjt.get(); System.out.println(resultInt); } }
运行结果:
165580141 成功生成(总时间:0 秒)
总算是得出不知道正错的满意结果来了。但是到底是由于什么原因导致的?