Java 8嵌套ParallelStream无法正常工作

时间:2014-09-02 14:54:28

标签: java java-8

package com.spse.pricing.client.main;

import java.util.stream.IntStream;

public class NestedParalleStream {

    int total = 0; 

    public static void main(String[] args) {

        NestedParalleStream nestedParalleStream = new NestedParalleStream();
        nestedParalleStream.test();
    }


    void test(){

        try{

            IntStream stream1 = IntStream.range(0, 2);
             stream1.parallel().forEach(a ->{
                IntStream stream2 = IntStream.range(0, 2);
                stream2.parallel().forEach(b ->{
                     IntStream stream3 = IntStream.range(0, 2);
                     stream3.parallel().forEach(c ->{
                         //2 * 2 * 2 = 8;
                         total ++;

                     });
                });
            });

             //It should display 8
            System.out.println(total); 

        }catch(Exception e){

            e.printStackTrace();
        }
    }
}

请帮助如何自定义parallestream以确保我们获得一致性结果。

4 个答案:

答案 0 :(得分:4)

由于多个线程递增total,您必须声明它volatile以避免竞争条件


编辑:volatile使读/写操作成为原子,但total++需要多于一个操作。因此,您应该使用AtomicInteger:

AtomicInteger total = new AtomicInteger();
...
total.incrementAndGet();

答案 1 :(得分:3)

语句total ++;中的问题它同时在多个线程中调用。

您应该使用synchronized或使用AtomicInteger

保护它

答案 2 :(得分:3)

LongAdderLongAccumulator优于AtomicLongAtomicInteger,其中多个线程正在改变该值并且其意图被相对较少次读取,例如一旦在计算结束时。加法器/累加器对象避免了原子对象可能发生的争用问题。 (double值有相应的加法器/累加器对象。)

通常有一种方法可以使用reduce()collect()重写累积。这些通常是优选的,特别是如果累积(或收集)的值不是longdouble

答案 3 :(得分:2)

关于可变性的一个主要问题是你解决它的方式。以您想要的方式解决问题的更好方法如下:

int total = IntStream.range(0,2)
            .parallel()
            .map(i -> {
                return IntStream.range(0,2)
                        .map(j -> {
                            return IntStream.range(0,2)
                                    .map(k -> i * j * k)
                                    .reduce(0,(acc, val) -> acc + 1);
                        }).sum();
            }).sum();