同时进行理解

时间:2015-06-04 19:45:22

标签: scala akka

根据这个blog post,理解存在潜在的性能问题。例如:

for {
  a <- remoteCallA()
  b <- remoteCallB()
} yield {
  (a, b)
}
remoteCallB完成之前,

remoteCallA被阻止。博客文章建议我们这样做:

futureA <- remoteCallA()
futureB <- remoteCallB()
for {
  a <- futureA
  b <- futureB
} yield {
  (a, b)
}

这将确保两个远程调用可以同时启动。

我的问题:以上(因此博客作者)是否正确?

我没有看到人们使用这种模式,这让我想知道是否存在通常使用的替代模式。

谢谢

2 个答案:

答案 0 :(得分:4)

理解

for {
  a <- remoteCallA()
  b <- remoteCallB()
} yield {
  (a, b)
}

转换为:

remoteCallA().flatmap(a => remoteCallB().map(b => (a,b)))

所以,是的,我相信这位博主是正确的,因为这些调用将是顺序的,而不是并发的。

答案 1 :(得分:2)

同时执行多个期货的常见模式是使用zipFuture.traverse。以下是一些例子:

for {
  (a, b) <- remoteCallA() zip remoteCallB()
} yield f(a, b)

当有超过2个期货时,这会变得有点麻烦:

for {
  ((a, b), c) <- remoteCall() zip remoteCallB() zip remoteCallC()
} yield (a, b, c)

在这些情况下,您可以使用Future.sequence

for {
  Seq(a, b, c) <- 
    Future.sequence(Seq(remoteCallA(), remoteCallB(), remoteCallC()))
} yield (a, b, c)

Future.traverse,如果您有一系列参数,并希望将相同的函数应用于所有参数,这将返回Future

但这两种方法都存在问题:如果其中一个Future提前失败,在其他方法完成之前,您自然可能希望生成的Future在此时立即失败。但事实并非如此。只有在所有期货完成后,结果Future才会失败。有关详细信息,请参阅此问题:How to implement Future as Applicative in Scala?