2017-12-08 10 views
0

私はJavaのaggeragate操作のパフォーマンス評価を行ってコレクションを反復処理していました。私はパフォーマンスstreamparallelStreamの評価をしていました。しかし、私はparallelStreamの出力がほとんどの時代で間違っていることを発見しました。JavaのparallelStreamが正しい結果を表示していません

public class ParallelStreamPerformance { 
    static int totaleven = 0; 
    public static void main(String[] args) { 
     List<Integer> randomList = new ArrayList<>(); 
     Random rnd = new Random(); 
     for(int i = 0 ;i < 1000;i++) { 
      int r = rnd.nextInt(500000); 
      randomList.add(r); 
     } 

     long s1 = System.currentTimeMillis(); 

     randomList.stream().filter(e -> e%2 ==0).forEach(e -> count()); 
     System.out.println("Even: "+totaleven); 
     long e1 = System.currentTimeMillis(); 
     System.out.println(e1 - s1); 

     totaleven = 0; 
     long s2 = System.currentTimeMillis(); 

     randomList.parallelStream().filter(e -> e%2 ==0).forEach(e -> count()); 
     System.out.println("Even: "+totaleven); 
     long e2 = System.currentTimeMillis(); 
     System.out.println(e2 - s2); 
    } 
    public static void count() { 
     totaleven++; 
    } 
} 

私の質問がされています:私は間違った方法でparallelStreamを使用しています次のコードでたとえば、私は時間のparallelStream以上80%未満からの間違った出力を得ましたか。 parallelStreamの正確性を保証する方法はありますか? ありがとう

+0

ベンチマーク方法は無益です。それはあなたに答えを与えるでしょうが、彼らは間違っているでしょう。 https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java –

+0

ありがとう@BrianGoetz –

+0

あなたの実際の質問が間違った結果を得ようとしているときは、無関係なベンチマークのものでそれを混乱させないでください。あなたのコードは10行に短縮される可能性があります。また、「パフォーマンス評価」を行っているあなたについての散文も時代遅れです。コードが正しく動作しない場合、そのパフォーマンスを測定する必要はありません。 – Holger

答えて

4

あなたのコードはcount()の方法で問題があると思います。 parallelStreamは同時にタスクを実行しようとします。このメソッドは​​にするか、totalevenをAtomtic Integerにすることができます。それが役に立てば幸い。

+0

はい、同期メソッドを使用して問題を解決します。ありがとう –

+1

だから、あなたのコードは_correct_ですが、スレッドがロックを待つすべての時間を費やすので、並列コードがシーケンシャルより速い(並列性を使用する唯一の理由です)可能性は低いです。あなたがしたいのは、共有可変カウンタをインクリメントするのではなく、 'count()'または 'reduce()'を使うことです。これは正しい(同期が必要ない)方がより簡単で、より並列性に優れています。 –

+0

@BrianGoetz:ストリームAPIに 'forEach'を追加するのは設計ミスであるかもしれません... – Holger

2

並列ストリームの結果には何が問題なのですか?それが小さすぎると、スレッドセーフではないので、おそらくtotaleven++に問題があります。 AtomicIntegerまたはその他のスレッドセーフなソリューションを使用してください。

3

の代わりにあなたが

totaleven = randomList.stream().filter(e -> e % 2 ==0).count(); 
totaleven = 0; 
totaleven = randomList.parallelStream().filter(e -> e % 2 ==0).count(); 

totalevenが長いか、鋳造が適用されるデータ型に変更する必要があります例えば、端末操作をStream:count

を使用することができますカウンタをインクリメントするためにはforEachを使用しました。

関連する問題