Fork/Join框架
java 5開始引入了Executor和ExecutorService接口以及實現這兩個接口的類之後,使得java在並發支持上得到了進一步的提升。
執行器框架(Executor Framework)將任務的創建和執行進行了分離,通過這個框架,只需要實現Runnable接口的對象和使用Executor對象,然後將Runnable對象發送給執行器。執行器再負責運行這些任務所需要的線程,包括線程的創建,線程的管理以及線程的結束。
java 7則更進一步,它包括了ExecutorService接口的另一種實現,用來解決特殊類型的問題,它就是Fork/Join框架,有時也稱分解/合並框架。
Fork/Join框架是用來解決能夠通過分治技術將問題拆分成小任務的問題。
在一個任務中,先檢查將要解決的問題的大小,如果大於一個設定的大小,那就將問題拆分成可以通過框架來執行的小任務。如果問題的大小比設定的大小要小,就可以直接在任務裏面解決這個問題,然後根據需要返回任務的結果。
沒有固定的公式來決定問題的參考大小,從而決定一個任務是需要進行拆分或者不需要拆分,拆分與否是依賴於任務本身的特性。
將ForkJoinPool類看作一個特殊的Executor執行器類型,這個框架基於以下兩種操作:
1.分解(Fork)操作:當需要將一個任務拆分成更小的多個任務時,在框架中執行這些任務。
2.合並(Join)操作:當一個主任務等待其創建的多個子任務的完成執行。
Fork/Join框架和執行器框架(Executor Framework)主要區別在於:工作竊取算法(Work-Stealing Algorithm)。
與執行器框架不同,使用Join操作讓一個主任務等待它所創建的子任務的完成,執行這個任務的線程稱之為工作者線程(Work Thread)。工作者線程尋找其他仍未被執行的任務,然後開始執行。通過這種方式,這些線程在運行時擁有所有的優點,進而提升應用程序的性能。
為了達到這個目標,通過Fork/Join框架執行的任務有以下限制:
1.任務只能使用fork()和join()操作當同步機制。如果使用其他的同步機制,工作者線程就不能執行其他任務,當然這任務是在同步操作裏時。比如,如果Fork/Join框架中將一個任務休眠,正在執行這個任務的工作者線程在休眠期內不能執行另一個任務。
2.任務不能執行I/O操作,比如文件數據的讀取與寫入。
3.任務不能拋出非運行時異常,必須在代碼中處理掉這些異常。
Fork/Join框架的核心是由以下兩個類組成的:
1.ForkJoinPool:這個類實現了ExecutorService接口和工作竊取算法。它管理工作者線程,並提供任務的狀態信息,以及任務的執行信息。
2.ForkJoinTask:這個類是一個將在ForkJoinPool中執行的任務的基類。
Fork/Join框架提供了再一個任務裏執行fork()和join()操作的機制和控制任務狀態的方法。
通常,為了實現Fork/Join任務,需要實現一個以下兩個類之一的子類:
1.RecursiveAction:用於任務沒有返回結果的場景。
2.RecursiveTask:用於任務有返回結果的場景。
Fork/Join框架