当计算a ^ b为什么并行不起作用但parallelStream可以 [英] when calculate a^b why parallel not work but parallelStream could

查看:198
本文介绍了当计算a ^ b为什么并行不起作用但parallelStream可以的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to calculate a^b , e.g. 2^30,

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

首先我用这种方式

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

得到了正确的结果。然后我想并行计算它,所以很自然地我把它改为

Got right result. Then I want to calculate it parallelly, so naturally I changed it to

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

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

but in this case the result is just 32. Why?

因此支持并行我再次更改

So for supporting parallel I changed it again

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

在这种情况下可行。

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

推荐答案

减少要求提供的函数。您的功能(acc,x) - > a * acc 不符合要求,因此违反了合同。

reduce requires that the supplied function be associative. Your function (acc, x) -> a * acc does not satisfy the requirement and thus violates the contract.

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

To be associative, the function must satisfy (x op y) op z == x op (y op z) for any x, y and z. But for your function, (x op y) op z = x*a^2 while x op (y op z) = x * a.

此外,提供给reduce的第一个参数必须是与累加器函数相关的标识。因此任何x的 1 op x == x 都必须如此。但是这也不适用于你的累加器函数,因为 1 op x == a

Furthermore, the first parameter supplied to reduce must be an identity with respect to the accumulator function. So it must be true that 1 op x == x for any x. But that also doesn't hold for your accumulator function since 1 op x == a.

正确的方法这样做是:

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

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

This is guaranteed to work correctly whether the stream is parallel or sequential.

这篇关于当计算a ^ b为什么并行不起作用但parallelStream可以的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆