私は 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 を使用している方法は機能しますが、まだ懸念が残っています。
- 私のアプローチは、ExecutorService を使用した優れたプログラミング プラクティスを超えていますか?
- ExecutorService のシングルトン インスタンスを使用する必要がありますか?
- 並列メソッド内の 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 で改善されましたか?
ヘルプ/ガイダンスをいただければ幸いです。