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以确保我们获得一致性结果。
答案 0 :(得分:4)
由于多个线程递增total
,,您必须声明它 volatile
以避免竞争条件
编辑:volatile使读/写操作成为原子,但total++
需要多于一个操作。因此,您应该使用AtomicInteger:
AtomicInteger total = new AtomicInteger();
...
total.incrementAndGet();
答案 1 :(得分:3)
语句total ++;
中的问题它同时在多个线程中调用。
您应该使用synchronized
或使用AtomicInteger
答案 2 :(得分:3)
LongAdder或LongAccumulator优于AtomicLong
或AtomicInteger
,其中多个线程正在改变该值并且其意图被相对较少次读取,例如一旦在计算结束时。加法器/累加器对象避免了原子对象可能发生的争用问题。 (double
值有相应的加法器/累加器对象。)
通常有一种方法可以使用reduce()
或collect()
重写累积。这些通常是优选的,特别是如果累积(或收集)的值不是long
或double
。
答案 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();