2014-01-16 32 views
23

我剛讀完這篇文章:What's the advantage of a Java-5 ThreadPoolExecutor over a Java-7 ForkJoinPool?,覺得答案不夠直。Java的Fork/Join與ExecutorService - 何時使用哪個?

您能用簡單的語言和示例來解釋Java 7的Fork-Join框架和舊的解決方案之間的權衡是什麼?

我也是從javaworld.com閱讀的話題Java Tip: When to use ForkJoinPool vs ExecutorService了谷歌的#1命中,但文章並沒有回答這個問題稱號時,它談論大多API差異...

回答

27

的fork-join允許你輕鬆執行分而治之的作業,如果您想在ExecutorService中執行它,則必須手動執行。在實踐中,ExecutorService通常用於同時處理許多獨立的請求(又名事務),並在您想要加速一個連貫的工作時進行分叉連接。

+5

+1 Fork-Join解決特定類型的問題。如果您沒有這種類型的問題,請使用ExecutorService,因爲這正是Fork-Join使用的方式。 –

+0

@JakubK好的。如果我有一張1000x1000的圖片需要處理,該怎麼辦?我可以把它分成前面或D&C時尚。然後怎樣呢?我也在考慮比較 - 許多任務與少數,長壽與短期,同等大小問題vs不等等。 – Parobay

+0

如果您可以分開處理所有部件,然後合併結果,則應使用fork-join –

22

叉連接特別適合遞歸問題,其中任務涉及運行子任務,然後處理其結果。 (這通常被稱爲「分而治之」......但並不能揭示基本特徵。)

如果您嘗試使用傳統線程(例如,通過ExecutorService)來解決像這樣的遞歸問題,您最終會線程綁在等待其他線程向他們傳遞結果。

另一方面,如果問題沒有這些特徵,使用fork-join並沒有真正的好處。


Here's a "Java Tips" article that goes into more detail:

4

fork-join框架是執行框架,特別是解決遞歸多線程程序「等待」問題的延伸。事實上,新的Fork-Join框架類都從Executor框架的現有類擴展而來。

有2個特點中央到fork-join框架

  • 工作竊取(空閒線程有任務 線程搶斷工作排隊超過了它目前可以處理)
  • 能力遞歸分解任務並收集結果。 (顯然,這要求必須與 概念並行處理概念的沿彈出...但在Java缺乏一個堅實的 實施框架,直到Java 7中)

如果並行處理的需求是嚴格遞歸的,除了去Fork-Join,別無選擇,否則執行者或Fork-Join框架都應該這樣做,儘管可以說Fork-Join可以更好地利用這些資源,因爲空閒線程正在「竊取」來自忙碌者的一些任務線程。

6

的Java 8提供了一個執行者更多的API

static ExecutorService newWorkStealingPool() 

創建使用所有可用的處理器作爲其目標並行水平工作竊取線程池。

隨着此API的添加,Executors提供了不同類型的ExecutorService選項。

根據您的要求,您可以選擇其中之一或者您可以看看ThreadPoolExecutor,它可以更好地控制有界任務隊列大小,RejectedExecutionHandler機制。

  1. static ExecutorService newFixedThreadPool(int nThreads)

    創建一個可重用不受限制的隊列操作線程的固定數目的線程池。

  2. static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

    創建一個線程池,它可安排命令的給定延遲後運行,或者定期地執行。

  3. static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)

    創建一個可根據需要創建新線程的線程池,但可用時將重用以前構造的線程,並使用提供的ThreadFactory時創建新的線程需要。

  4. static ExecutorService newWorkStealingPool(int parallelism)

    創建維持足夠的線程來支持給定的並行水平,並且可以使用多個隊列來減少爭一個線程池。

每個API的有針對性地滿足您的應用程序的各個業務需求。使用哪一個將取決於您的使用案例要求。

例如

  1. 如果要處理所有提交的任務到達順序,只需使用newFixedThreadPool(1)

  2. 如果你想優化的遞歸任務大的計算性能,使用ForkJoinPool或​​

  3. 如果要定期執行某些任務或將來某個時間執行某些任務,請使用newScheduledThreadPool

看一看更好article通過PeterLawrey關於ExecutorService用例。

相關SE問題:

java Fork/Join pool, ExecutorService and CountDownLatch

4

叉加入是ExecuterService的實現。主要的區別是這個實現創建DEQUE工作池。哪裏的任務是從單方面插入,但從任何一方撤回。這意味着如果您創建了new ForkJoinPool(),它將查找可用的CPU並創建多個工作線程。然後它將負載均勻分配到每個線程中。但是,如果一個線程工作緩慢而其他線程速度很快,他們將從慢線程中選擇任務。從背面。以下步驟將更好地說明盜竊行爲。

階段1(最初):
W1 - > 5,4,3,2,1
W2 - > 10,9,8,7,6

階段2:
W1 - > 5,4
W2 - > 10,9,8,7,

階段3:
W1 - > 10,5,4
W2 - > 9,8,7,

鑑於執行人Servi大街ce創建被詢問的線程數量,並應用阻塞隊列來存儲所有剩餘的等待任務。如果您已使用cachedExecuterService,它將爲每個作業創建單個線程,並且不會有等待隊列。