java中parallelStream中的Bug
有人能告诉我为什么会发生这种情况,这是预期的行为还是一个bug吗java中parallelStream中的Bug,java,filter,stream,reduce,parallelstream,Java,Filter,Stream,Reduce,Parallelstream,有人能告诉我为什么会发生这种情况,这是预期的行为还是一个bug吗 List<Integer> a = Arrays.asList(1,1,3,3); a.parallelStream().filter(Objects::nonNull) .filter(value -> value > 2) .reduce(1,Integer::sum) List a=Arrays.asList(1,1,3,3); a、 parallelStream
List<Integer> a = Arrays.asList(1,1,3,3);
a.parallelStream().filter(Objects::nonNull)
.filter(value -> value > 2)
.reduce(1,Integer::sum)
List a=Arrays.asList(1,1,3,3);
a、 parallelStream().filter(对象::非空)
.filter(值->值>2)
.reduce(1,整数::和)
回答:10
但是如果我们使用
stream
而不是parallelStream
,我得到了正确的预期的答案7
减少的第一个参数称为“identity”,而不是“initialValue”
1
根据加法没有标识1
是乘法的标识
但是,如果要对元素求和,则需要提供0
Java使用“identity”而不是“initialValue”,因为这个小技巧允许轻松地并行化
reduce
在并行执行中,每个线程将在流的一部分上运行reduce,当线程完成时,它们将使用完全相同的reduce函数进行组合 虽然它看起来像这样:
mainThread:
start thread1;
start thread2;
wait till both are finished;
thread1:
return sum(1, 3); // your reduce function applied to a part of the stream
thread2:
return sum(1, 3);
// when thread1 and thread2 are finished:
mainThread:
return sum(sum(1, resultOfThread1), sum(1, resultOfThread2));
= sum(sum(1, 4), sum(1, 4))
= sum(5, 5)
= 10
我希望您能看到,发生了什么以及为什么结果不是您期望的。检查
reduce
:“…标识值必须是累加器函数的标识。这意味着对于所有x
,累加器。应用(标识,x)
等于x
。”-不是1
和Integer::sum
能够使用并行流的情况,减少是分部分进行的,每个部分添加一个(可能每个元素一次)-使用0
进行尝试,结果应该是正确的,但为什么流的结果不同?因为非并行流按顺序工作。我将在几分钟后的回答中提供一个示例Hanks@Benjamin这非常有帮助。有趣的是:算法有点不同-identity
即使值被过滤掉也会被添加:IntStream.range(01100).parallel().filter(v->v<0).reduce(1,Integer::sum)
(36
使用jshell 1.15)@用户15244370是的。结果取决于使用的线程数。您的示例给出:4
用于1个线程,12
用于2个线程,20
用于4个线程,36
用于8个线程。我猜除了线程计数之外还有一个块大小,因此每个线程一次只计算N个元素,完成后将得到下一个N个元素。