JDK8では、parallelStreamを使用しているときにいくつのスレッドが生成されますか?たとえば、コードでは:
list.parallelStream().forEach(/** Do Something */);
このリストに100000個のアイテムがある場合、いくつのスレッドが生成されますか?
また、各スレッドは同じ数のアイテムを取得して作業しますか、それともランダムに割り当てられますか?
Oracleの並列ストリームの実装[1]は現在のスレッドを使用し、それに加えて、必要に応じて、デフォルトのフォーク結合プールForkJoinPool.commonPool()
を構成するスレッドも使用します。 CPUのコアの数。
共通プールのデフォルトサイズは、次のプロパティで変更できます。
-Djava.util.concurrent.ForkJoinPool.common.parallelism=8
または、独自のプールを使用できます。
ForkJoinPool myPool = new ForkJoinPool(8);
myPool.submit(() ->
list.parallelStream().forEach(/* Do Something */);
).get();
順序については、特定の順序ではなく、スレッドが使用可能になるとすぐにジョブが実行されます。
@Holgerが正しく指摘しているように、これは実装固有の詳細です(ドキュメントの最後に 1つのあいまいな参照 があります)。どちらのアプローチもOracleのJVMでは機能しますが、JVMでの動作は保証されません他のベンダーから、このプロパティはOracle以外の実装に存在できず、StreamsはForkJoinTask.fork
の動作に基づいて代替を内部的にレンダリングするForkJoinPool
を使用することもできませんでした( 参照こちら 詳細についてはこちら)。
@uraimoは正しいですが、答えは「Do Something」が何をするかによって異なります。 parallel.streams APIは、いくつかの興味深い問題があるCountedCompleterクラスを使用します。 F/Jフレームワークは結果を保持するために別個のオブジェクトを使用しないため、長いチェーンはOOMEをもたらす可能性があります。また、これらの長いチェーンは、スタックオーバーフローを引き起こすことがあります。これらの問題に対する答えは、 この記事 で指摘したように、パラクショナルテクニックの使用です。
もう1つの問題は、ネストされた並列forEachを使用する場合の過剰なスレッド作成です。