在參考資料中,對斐波納契數(shù)列(Fibonacci)進行求解來展示RecursiveTask的用法,很好。
另外,在JSR166y演進的過程中,其算法經(jīng)過調(diào)整,導(dǎo)致原示范代碼中存在一些問題,需要進行些許調(diào)整。歷史遺留代碼,如下:
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
f2.fork();
return f2.join() + f1.join();
但現(xiàn)在已不建議使用。真要如此執(zhí)行,會一直阻塞等待(至少我本機是如此)。查看RecursiveTask的源代碼,也發(fā)現(xiàn)示范doc中,兩個RecursiveTask類型結(jié)果相互匯聚,推薦示范為:
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
return f2.compute() + f1.join();
嗯,這里同時提供一個單線程版本的參考實現(xiàn),與之作為對比:
在測試時,發(fā)現(xiàn)速度太慢,于是萌生了改進了其算法的想法,于是一個非遞歸、單線程版本實現(xiàn)出現(xiàn)了:
使用JUNIT 4進行測試類:
該貼的代碼,都貼完了,可以預(yù)測一下哪一個算法的速度排名嗎 ?嗯,貼出運行JUNIT測試輸出結(jié)果吧:
Fork/Join 算法 ...
1836311903
用時 : 2203
單線程遞歸算法 ...
1836311903
用時 : 1016
單線程改進遞增算法 ...
1836311903
用時 : 0
在測試類中,把MAX設(shè)置為55或更大的數(shù)字,以上兩個算法就可能等待過長的時間(實在沒有耐心等待那么長時間),而算法三,即使設(shè)置再大,也是瞬時完成。
上面的測試類中,把results數(shù)組以static修飾,公共共享方式,存放在常量區(qū),在速度上會比原始測試代碼讀取方面更為迅速,快了不少。
本機的CPU雙核的效果沒有體現(xiàn)出來。權(quán)威一些的解析:
在Java 7 生命周期內(nèi),大的(32+)多核系統(tǒng)將大量出現(xiàn),有了這個框架可以讓人們對計算密集型任務(wù)獲得相對簡單的增速方法。目前,forkjoin在如Sun Niagaras和Azuls這樣的機器上工作得最好,它們只是即將普及的并行處理器。Forkjoin在標準SMP上工作的也不錯。總體來講,少于4處理器的話你不并能獲得太多增速效果——其主要目標是針對成打到成百處理器范圍。
另一方面,也是任務(wù)劃分過于細小,優(yōu)勢體現(xiàn)不出來。當然,不是所有的任務(wù)都適合Fork/Join模式,以及適合多線程,就看具體任務(wù)具體分析了。