7

私は ExecutorService クラスを学び始めています。ドキュメント (およびオンラインのチュートリアル) には、常に ExecutorService.shutDown() を呼び出してリソースを再利用するように記載されています。ただし、ドキュメントには、shutDown() を呼び出した後は、新しいタスクは受け入れられないとも記載されています。それで、私の質問は、データ処理を並列化する必要があるときはいつでも、新しい ExecutorService をインスタンス化する必要があるのですか?

現在、Callable オブジェクトのリストがあり、次のことを行います。

public void someMethod() {
 List<OuterCallable> outerCallables = getOuterCallables();
 ExecutorService executor = Executor.newFixedThreadPool(NUM_CPUS);
 executor.invokeAll(tasks);
 executor.shutDown();
}

ただし、私の OuterCallable もデータを分割したり、InnerCallable を使用して並列にデータ処理を実行したりします。

public class OuterCallable implements Callable<Long> {
 public Long call() throws Exception {
  long result = 0L;

  List<InnerCallable> innerCallables = getInnerCallables();
  ExecutorServices executor = Executor.newFixedThreadPool(NUM_CPUS);
  executor.invokeAll(tasks);
  executor.shutDown();

  return result;
 }
}    

それが ExecutorService のためだったのか、Fork/Join アプローチのためだったのか思い出せませんが、データを操作するための実際の並列手順には I/O 操作を含めるべきではなく、すべてをメモリ内で実行する必要があると述べているドキュメントとチュートリアルを覚えています。ただし、私の InnerCallable では、実際に JDBC 呼び出しを行っています (ここには示されていません)。

最終的に、私が ExecutorService を使用している方法は機能しますが、まだ懸念が残っています。

  1. 私のアプローチは、ExecutorService を使用した優れたプログラミング プラクティスを超えていますか?
  2. ExecutorService のシングルトン インスタンスを使用する必要がありますか?
  3. 並列メソッド内の I/O 操作だけでなく、JDBC 呼び出しも回避する必要がありますか?

最後の懸念事項として、Fork/Join と ExecutorService について少し調べてみました。Fork/Join API/クラスを完全に爆破した記事に出くわしました。Fork/Join を学ぶ価値はありますか? Stackoverflow などに関する記事をいくつか見ました。ここでは、テストを使用して Fork/Join と ExecutorService を比較し、Fork/Join と ExecutorService の CPU 使用率が向上していることを示すグラフがあります (Windows タスク マネージャー経由)。ただし、ExecutorService (JDK 1.7.x) を使用すると、CPU 使用率が最大になります。ExecutorService は最新の JDK で改善されましたか?

ヘルプ/ガイダンスをいただければ幸いです。

4

1 に答える 1

4

Callables が終了するのを待たずに戻るawaitTerminationため、呼び出しを追加する必要があります。shutDownそれ以外、

  1. OuterCallableシーケンシャルな依存関係がありますか? その場合、あなたのアプローチは問題ありませんが、ForkJoinPool を使用すると、ワーカー スレッドの数を低く抑えることができるため、望ましいでしょう。そうでない場合は、フラット化された の大きなコレクションをCallable単一の に送信することをお勧めしExecutorます。
  2. いくつかの異なるルーチンで ExecutorService を使用し、その受け渡しを避けたい場合のみ。でのみ使用さsomeMethodれる場合は、行っているようにそこでインスタンス化することもできます。
  3. 完了までに時間がかかる I/O ルーチンは避ける必要があります。ExecutorService に 4 つのワーカー スレッドがあり、それらすべてが I/O でブロックされている場合、他の Callables が CPU を集中的に使用する作業を待機している場合でも、JVM は CPU をまったく使用しません。クエリの完了に時間がかからない限り、いくつかの JDBC 呼び出しは問題ありません。
于 2012-02-27T13:22:28.317 に答える