77

この投稿を読み終えたところです: Java-7 ForkJoinPool に対する Java-5 ThreadPoolExecutor の利点は何ですか? 答えはまっすぐではないと感じました。

Java 7 の Fork-Join フレームワークと古いソリューションの間のトレードオフは何か、簡単な言葉と例で説明できますか?

私はまた、Google の #1 ヒットのトピックJava Tip: When to use ForkJoinPool vs ExecutorService from javaworld.comを読みましたが、この記事ではタイトルの質問答えていません。

4

6 に答える 6

44

fork-join は、タスクにサブタスクの実行とその結果の処理が含まれる再帰的な問題に特に適しています。(これは通常、「分割統治」と呼ばれますが、本質的な特徴は明らかにされていません。)

このような再帰的な問題を従来のスレッド化を使用して (ExecutorService などを介して) 解決しようとすると、他のスレッドが結果を配信するのを待ってスレッドが拘束されてしまいます。

一方、問題にこれらの特性がない場合、fork-join を使用しても実際のメリットはありません。


参考文献:

于 2014-01-16T09:17:42.450 に答える
25

Java 8 は Executor でもう 1 つの 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またはnewWorkStealingPool

  3. いくつかのタスクを定期的に、または将来の特定の時間に実行する場合は、newScheduledThreadPool

ユース ケースに関するもう 1 つのすばらしい記事をご覧ください。PeterLawreyExecutorService

関連する SE の質問:

Java Fork/Join プール、ExecutorService および CountDownLatch

于 2016-01-21T11:12:08.303 に答える
7

Fork Join は ExecuterService の実装です。主な違いは、この実装では DEQUE ワーカー プールが作成されることです。タスクが片側から挿入され、いずれかの側から取り消される場合。これは、作成new ForkJoinPool()した場合、使用可能な CPU を探して、その数のワーカー スレッドを作成することを意味します。次に、負荷を各スレッドに均等に分散します。しかし、1 つのスレッドの動作が遅く、他のスレッドの動作が速い場合、それらは遅いスレッドからタスクを選択します。裏側から。以下の手順は、盗みをよりよく示しています。

ステージ 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,

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

于 2017-08-04T12:45:41.200 に答える