java - 当计算 a^b 时,为什么 parallel 不起作用但 parallelStream 可以

标签 java parallel-processing java-8 java-stream reduce

我想计算 a^b ,例如2^30,

public long pow(final int a, final int  b)

首先我用的是这种方式

return LongStream.range(0, b).reduce(1, (acc, x) -> a * acc); // 1073741824

得到正确的结果。那我要并行计算,自然就改成了

return LongStream.range(0, b).parallel().reduce(1, (acc, x) -> a * acc); // 32

但在这种情况下,结果只是 32。为什么?

所以为了支持并行我又改了一遍

return Collections.nCopies(b,a).parallelStream().reduce(1, (acc, x) -> acc * x); // 1073741824

在这种情况下它有效。

那么并行方式有什么问题呢?

最佳答案

reduce要求提供的函数是 associative .您的函数 (acc, x) -> a * acc 不满足要求,因此违反了契约(Contract)。

要关联,函数必须满足 (x op y) op z == x op (y op z) 对于任何 x、y 和 z。但是对于您的函数,(x op y) op z = x*a^2x op (y op z) = x * a

此外,提供给 reduce 的第一个参数必须是累加器函数的标识。所以对于任何 x,1 op x == x 一定是真的。但这也不适用于您的累加器函数,因为 1 op x == a

正确的做法是:

LongStream.range(0, b).map(x -> a).reduce(1, (u, v) -> u * v);

无论流是并行的还是顺序的,这都能保证正常工作。

关于java - 当计算 a^b 时,为什么 parallel 不起作用但 parallelStream 可以,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44013553/

相关文章:

java - Optional.flatMap 和 Optional.map 有什么区别?

java - new String(byte []) 结果在 JDK 7 和 8 中不同

Java递归问题: Minesweeper

java - 正则表达式在双引号上分割字符串仅保留引号之间的内容

Perl,如何从 url 并行获取数据?

c++ - 将执行从一个线程转移到另一个线程以实现任务并行性和 future 调用

java - ConcurrentSkipListMap 如何使删除和添加调用原子化

java - 我该如何解决 "Cannot make a static reference to the non-static field or method"?

java - 在 SQLite 上运行更新时为 "No such column"

r - 如何在 R 中并行化分组变异/总结