2016-12-12 6 views
1

Javaストリームは、ハードウェアの並列処理量に基づいています。しかし、もし私がいつも最大限の並列処理をしたいのであれば?Java 8ストリームでの並列処理の最大化

次のコードを検討してください。 10個のタスクのそれぞれを100ミリ秒間同時に実行したい。

long runUntil = System.currentTimeMillis() + 100; 
IntStream.range(0, 10).parallel().forEach(i -> 
{ 
    int cnt = 0; 
    while(System.currentTimeMillis() < runUntil) 
     cnt++; 
    System.out.println(i + ": " + cnt); 
}); 

しかし、私が得る結果は次のとおりです。

2: 56443 
1: 67506 
4: 74693 
6: 70549 
0: 0 
3: 0 
5: 0 
7: 0 
8: 0 
9: 0 

だから、唯一の4つのタスクを並列に実行され、最初の4の1が終了したときに第五タスクのみを開始します。私はすべてのタスクをほぼ同じ時間に開始し、お互いを待たないようにします。

Custom thread pool in Java 8 parallel streamの複製であることに同意しません。なぜなら、この質問は他のタスクをブロックする処理が遅いということですが、私の場合は、(できる限り)並列性を最大化するStream APIを使用します。そうパラレルタスクが同時に実行される

Runtime.getRuntime().availableProcessors(); // 4 in your case 

+1

期待される結果は何ですか? –

+6

あなたは4つのコアを持っているようです。 – 4castle

+0

'を同時に100ミリ秒実行する:a)すべてのタスクを同時に開始するか、b)100ms実行するまで終了しないかを指定しますか? –

答えて

4

パラレルストリームを実行すると、あなたがForkJoinPoolを呼び出すフードの下には、そのプールの結果に等しい作業スレッドの数を有しています4スレッド分。唯一これ偽

while(System.currentTimeMillis() < runUntil) 

レポート、ゼロ:あなたは第五タスク(100ミリ秒が経過している)ので、この状態を開始する時までに

。同様に、この答えで説明したように

https://stackoverflow.com/a/22269778/2947592)、あなたはForkJoinPoolを自分で作成することができ、この問題を解決するために

long runUntil = System.currentTimeMillis() + 1000; 
ForkJoinPool forkJoinPool = new ForkJoinPool(10); // 10 Threads 
forkJoinPool.submit(() -> 
IntStream.range(0, 10).parallel().forEach(i -> { 
    int cnt = 0; 
    while (System.currentTimeMillis() < runUntil) 
     cnt++; 
    System.out.println(i + ": " + cnt); 
})).get(); 
+1

@wvdz私はあなたが提供した答えを見てきましたが、あなたの問題を修正しました。しかし、あなたが持っているコアより多くのスレッドをマッピングするのは良い考えではありません。あなたのユースケースについて説明するのは間違いありませんか?私は本当に興味があります。各コアがどのくらい速く追加を行うかを測定するだけなら、4つのコアに10のスレッドを割り当てると、結果が悪くなります。 – Eugene

+0

これは良い考えではないかもしれませんが、私が取り組んでいることの要件です。もう1つの解決策は、手動でスレッドを起動することですが、私はむしろストリームAPIを使用したいと思います。 – wvdz

+2

@wvdzプロダクション環境では、スレッドが手動で起動され、何が起きているのかを人々が知ることができます。 'mapToObject'を実行してそこにスレッドを作成することができます。 – 4castle

1

だから私はすでに自分の質問への答えを見つけました。問題は実際にはハックのように感じられ、適切な解決策ではないということです。私は、これを実稼働環境で使用するのは快適ではありません。

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "10"); 

今、私はそれが1000ミリ秒のために実行させたときに、このような結果が得られます:

9: 40158551 
8: 41835052 
0: 39087202 
4: 37993773 
6: 37993442 
7: 36503041 
2: 40076207 
1: 37894657 
5: 35785211 
3: 40086037 

私は私の要件は合理的だと思うし、それはapparantlyストリームAPIによってサポートされていない驚いています。

+2

もう一度質問と回答は[Java 8並列ストリームのカスタムスレッドプール]の複製です(http://stackoverflow.com/questions/21163108/custom-thread-pool-in-java-8-parallel-ストリーム) –

関連する問題