我正在对Java aggeragate操作进行一些性能评估,以迭代集合。我正在对效果stream
和parallelStream
进行评估。但我发现大多数时候parallelStream
的输出都是错误的。例如,在以下代码中,parallelStream
的输出错误超过80%:
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
的正确性。
感谢
答案 0 :(得分:4)
我认为您的代码遇到了count()
方法的问题。由于parallelStream
将尝试同时执行任务。此方法应为synchronized
,或者您可以将totaleven
设为Atomtic Integer。希望它有所帮助。
答案 1 :(得分:3)
您可以使用终端操作Stream:count
,而不是使用forEach递增计数器例如
totaleven = randomList.stream().filter(e -> e % 2 ==0).count();
totaleven = 0;
totaleven = randomList.parallelStream().filter(e -> e % 2 ==0).count();
totaleven需要更改为数据类型long或者应用了cast。
答案 2 :(得分:2)
并行流结果有什么问题?如果它太小,那么很可能你有totaleven++
的问题,因为它不是线程安全的。使用AtomicInteger或任何其他线程安全解决方案。