2014-01-16 16 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上のGoogleの#1ヒットを読むが、記事では、タイトルの質問に答えていない、それはあなたができますほとんどが...

答えて

27

フォーク参加APIの違いについて語りますExecutorServiceで実行したい場合は手動で実装する必要がある分割と征服のジョブを簡単に実行できます。実際にはExecutorServiceは多くの独立した要求(トランザクションとも呼ばれる)を同時に処理するために使用され、1つの一貫性のあるジョブを高速化したいときはfork-joinになります。

+5

+1 Fork-Joinは、特定の種類の問題を解決します。このタイプの問題がない場合は、ExecutorServiceを使用します。これは、Fork-Joinが使用するものです。 –

+0

@JakubK OK。処理する画像が1000x1000の場合はどうなりますか?私はそれを前面またはD&Cの方法で分割することができます。それでは?私はまた、比較について考えていました - 多くのタスクvs数少ない、長寿命vs短い、等しいサイズの問題vsなど。 – Parobay

+0

すべての部分を別々に処理して結果を結合できる場合は、fork-join –

22

フォーク結合は、サブタスクの実行とその結果の処理を含む、再帰の問題に特に適しています。

従来のスレッディング(ExecutorServiceなど)を使用してこのような再帰的な問題を解決しようとすると、最終的には終了しますスレッドが結ばれて他のスレッドが結果を配信するのを待っています。

一方、問題にそのような特性がない場合、fork-joinを使用することによる実質的な利点はありません。


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

4

フォーク-参加の枠組みは、特に再帰的なマルチスレッドプログラムでの問題「を待っている」対処するためのフレームワークをエグゼキュータにする拡張機能です。実際、新しいFork-Joinフレームワーククラスは、すべてExecutorフレームワークの既存のクラスから拡張されています。

フォーク-参加の中心2つの特徴がありますフレームワーク

  • 盗む仕事を再帰的に分解する
  • 能力を(アイドルスレッドが現在処理できる以上のことをキューに入れられたタスク を持つスレッドから仕事を盗みます)タスクを実行し、結果を収集します。 (どうやら、この要件は、並列処理の概念の 概念と一緒にポップアップ表示...が、Java 7までJavaで固体 実装の枠組みを欠いている必要があります)

並列処理のニーズが厳密であれば再帰的に、フォーク・ジョインに行くという選択肢はありません。そうでなければ、実行中のフォーク・ジョイン・フレームワークのどちらかがすべきですが、フォーク・ジョインは、アイドル・スレッドがより忙しいスレッド。

6

のJava 8は、エグゼキュータ

static ExecutorService newWorkStealingPool() 

内の1つの以上のAPIがその標的の並列レベルとして利用可能なすべてのプロセッサを使用してワークスチールスレッドプールを作成し提供します。

このAPIを追加すると、Executorsはさまざまなタイプのオプションを提供します。

要件に応じて、いずれかを選択するか、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. あなたは再帰的なタスクの大きな計算のパフォーマンスを最適化したい場合は、単にForkJoinPoolまたは​​

  2. を使用し、newFixedThreadPool(1)

  3. を使用し、到着順にすべて提出したタスクを処理する場合定期的に、または特定の時期に特定のタスクを実行したい場合は、newScheduledThreadPool

もう一つ見てみましょうarticlePeterLawreyExecutorServiceの使用例です。

関連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、

キュータ一方サービス要求された数のスレッドを作成し、残りのすべての待機タスクを格納するブロッキングキューを適用します。 cachedExecuterServiceを使用した場合は、ジョブごとに単一のスレッドが作成され、待機キューは存在しません。

関連する問題