在参考资料中,对斐波纳契数列(Fibonacci)进行求解来展示RecursiveTask的用法,很好。
另外,在JSR166y演进的过程中,其算法经过调整,导致原示范代码中存在一些问题,需要进行些许调整。历史遗留代码,如下:
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
f2.fork();
return f2.join() + f1.join();
但现在已不建议使用。真要如此执行,会一直阻塞等待(至少我本机是如此)。查看RecursiveTask的源代码,也发现示范doc中,两个RecursiveTask类型结果相互汇聚,推荐示范为:
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
return f2.compute() + f1.join();
嗯,这里同时提供一个单线程版本的参考实现,与之作为对比:
在测试时,发现速度太慢,于是萌生了改进了其算法的想法,于是一个非递归、单线程版本实现出现了:
使用JUNIT 4进行测试类:
该贴的代码,都贴完了,可以预测一下哪一个算法的速度排名吗 ?嗯,贴出运行JUNIT测试输出结果吧:
Fork/Join 算法 ...
1836311903
用时 : 2203
单线程递归算法 ...
1836311903
用时 : 1016
单线程改进递增算法 ...
1836311903
用时 : 0
在测试类中,把MAX设置为55或更大的数字,以上两个算法就可能等待过长的时间(实在没有耐心等待那么长时间),而算法三,即使设置再大,也是瞬时完成。
上面的测试类中,把results数组以static修饰,公共共享方式,存放在常量区,在速度上会比原始测试代码读取方面更为迅速,快了不少。
本机的CPU双核的效果没有体现出来。权威一些的解析:
在Java 7 生命周期内,大的(32+)多核系统将大量出现,有了这个框架可以让人们对计算密集型任务获得相对简单的增速方法。目前,forkjoin在如Sun Niagaras和Azuls这样的机器上工作得最好,它们只是即将普及的并行处理器。Forkjoin在标准SMP上工作的也不错。总体来讲,少于4处理器的话你不并能获得太多增速效果——其主要目标是针对成打到成百处理器范围。
另一方面,也是任务划分过于细小,优势体现不出来。当然,不是所有的任务都适合Fork/Join模式,以及适合多线程,就看具体任务具体分析了。