Java 8 並列ストリーム用のカスタム スレッド プール
Java 8 並列ストリームの領域では、次のような疑問が生じます。特定のタスク用のカスタム スレッド プール?広範な検索にも関わらず、この機能は多くの開発者に知られていません。
並列ストリームが必要なマルチスレッド サーバー アプリケーションを考えてみましょう。ただし、区分化を維持し、あるモジュールのタスクが他のモジュールをブロックしないようにするには、モジュールごとに異なるスレッド プールが必要です。
問題を説明するために、次の例を考えてみましょう。
ExecutorService es = Executors.newCachedThreadPool(); es.execute(() -> runTask(1000)); // incorrect task es.execute(() -> runTask(0)); es.execute(() -> runTask(0)); es.execute(() -> runTask(0)); es.execute(() -> runTask(0)); es.execute(() -> runTask(0));
この例では、不自然な例では、CPU 負荷の高いタスクが Executors.newCachedThreadPool() を使用して並列実行されます。最初のタスクは、シミュレートされたスレッド スリープによって意図的に速度が低下します。その結果、他のタスクは完了を待って停止状態になります。これは、あるモジュールの遅いタスクが他のモジュールのタスクをどのように妨げるかを示しています。
ただし、このジレンマには賢明な解決策があります。特定の fork-join プール内のタスクとして並列操作を実行する。そうすることで、他の並列ストリーム操作で使用される共通の fork-join プールから隔離されたままになります。
final int parallelism = 4; ForkJoinPool forkJoinPool = null; try { forkJoinPool = new ForkJoinPool(parallelism); final List<Integer> primes = forkJoinPool.submit(() -> // Parallel task here, for example IntStream.range(1, 1_000_000).parallel() .filter(PrimesPrint::isPrime) .boxed().collect(Collectors.toList()) ).get(); System.out.println(primes); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } finally { if (forkJoinPool != null) { forkJoinPool.shutdown(); } }
この手法では、ForkJoinTask.fork() を利用します。これにより、現在のタスクがfork-join プールの場合、非同期実行はそのプール内で発生する必要があります。それ以外の場合は、ForkJoinPool.commonPool() が使用されます。
このアプローチを利用すると、パフォーマンスやタスクの区分化を損なうことなく、マルチスレッド アプリケーション内のさまざまなモジュールで並列ストリームを安全に使用できます。
以上がJava 8 並列ストリームはタスク分離にカスタム スレッド プールを使用できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。