web-dev-qa-db-ja.com

Java 8でparallelStreamに生成されるスレッドの数は?

JDK8では、parallelStreamを使用しているときにいくつのスレッドが生成されますか?たとえば、コードでは:

list.parallelStream().forEach(/** Do Something */);

このリストに100000個のアイテムがある場合、いくつのスレッドが生成されますか?

また、各スレッドは同じ数のアイテムを取得して作業しますか、それともランダムに割り当てられますか?

53
SinnerShanky

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を使用することもできませんでした( 参照こちら 詳細についてはこちら)。

56

@uraimoは正しいですが、答えは「Do Something」が何をするかによって異なります。 parallel.streams APIは、いくつかの興味深い問題があるCountedCompleterクラスを使用します。 F/Jフレームワークは結果を保持するために別個のオブジェクトを使用しないため、長いチェーンはOOMEをもたらす可能性があります。また、これらの長いチェーンは、スタックオーバーフローを引き起こすことがあります。これらの問題に対する答えは、 この記事 で指摘したように、パラクショナルテクニックの使用です。

もう1つの問題は、ネストされた並列forEachを使用する場合の過剰なスレッド作成です。

3
edharned