fork/join框架Java

Fork/Join框架是Java7提供了的一個用於並行執行任務的框架, 是一個把大任務分割成若干個小任務,最終彙總每一個小任務結果後獲得大任務結果的框架。html

Fork/Join使用兩個類:java

  • ForkJoinTask:咱們要使用ForkJoin框架,必須首先建立一個ForkJoin任務。它提供在任務中執行fork()和join()操做的機制,ork/Join框架提供瞭如下兩個子類:
    • RecursiveAction:用於沒有返回結果的任務。
    • RecursiveTask :用於有返回結果的任務。
  • ForkJoinPool :ForkJoinTask須要經過ForkJoinPool來執行,任務分割出的子任務會添加到當前工做線程所維護的雙端隊列中。

ForkJoinPool是一個執行ForkJoinTask的ExecutorService,ForkJoinPool提供no-ForkJoinTask客戶端提交的入口點,以及管理和監視操做。算法

ForkJoinPool與其餘類型的ExecutorService的不一樣之處主要在於使用工做竊取:池中的全部線程都嘗試查找和執行提交給池的任務和/或由其餘活動任務建立的任務(若是不存在則最終阻止等待工做)。當大多數任務產生其餘子任務時(如大多數ForkJoinTasks),以及從外部客戶端向池提交許多小任務時,這能夠實現高效處理。特別是在構造函數中將asyncMode設置爲true時,ForkJoinPools也可能適用於從未加入的事件樣式任務。api

static commonPool()適用於大多數應用程序,common pool由未顯式提交到指定池的任何ForkJoinTask使用。使用common pool一般會減小資源使用(其線程在不使用期間緩慢回收,並在後續使用時恢復)。oracle

而後咱們寫一個demo,這裏DoTask繼承了RecursiveAction,裏面的有start和end,還有最多處理list中THRESHOLD條數據。框架

而後咱們運行一下:async

輸出:函數

對於須要單獨或自定義pool的應用程序,可使用給定的目標並行度級別構造ForkJoinPool;默認狀況下,等於可用處理器的數量。。線程

默認狀況下,common pool使用默認參數構造,但能夠經過設置三個系統屬性來控制它們:翻譯

此實現將最大運行線程數限制爲32767.嘗試建立大於最大數量的池會致使IllegalArgumentException。

僅當pool關閉或內部資源耗盡時,此實現纔會拒絕提交的任務(即經過拋出RejectedExecutionException)。

下面摘錄一段(https://www.cnblogs.com/wanly3643/p/3956801.html),等我看了Doug Lea大神的,再寫一點:

仔細看了Doug Lea的那篇文章:A Java Fork/Join Framework 中關於Work-Stealing的部分,下面列出該算法的要點(基本是原文的翻譯):

1. 每一個Worker線程都維護一個任務隊列,即ForkJoinWorkerThread中的任務隊列。

2. 任務隊列是雙向隊列,這樣能夠同時實現LIFO和FIFO。

3. 子任務會被加入到原先任務所在Worker線程的任務隊列。

4. Worker線程用LIFO的方法取出任務,也就後進隊列的任務先取出來(子任務老是後加入隊列,可是須要先執行)。

5. Worker線程的任務隊列爲空,會隨機從其餘的線程的任務隊列中拿走一個任務執行(所謂偷任務:steal work,FIFO的方式)。

6. 若是一個Worker線程遇到了join操做,而這時候正在處理其餘任務,會等到這個任務結束。不然直接返回。

7. 若是一個Worker線程偷任務失敗,它會用yield或者sleep之類的方法休息一下子,再嘗試偷任務(若是全部線程都是空閒狀態,即沒有任務運行,那麼該線程也會進入阻塞狀態等待新任務的到來)。

Doug Lea

參考:

http://ifeve.com/java-fork-join-framework/#more-35602

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html

http://gee.cs.oswego.edu/dl/papers/fj.pdf()

 

有什麼討論的內容,能夠加我公衆號:

相關文章
相關標籤/搜索