我有两个在 Future 中发生的计算,如下所示:

val comp1 = Future { ... }
val comp2 = Future { ... }

我希望它运行时 comp2 总是在 comp1 完成后运行!我知道使用for表达式,我可以组合这两个Future之类的。
for {
  comp1Result <- comp1
  comp2Result <- comp2
} yield { ... }

在 comp2 之前完成 comp1 的保证是什么?我的意思是这些是发生在不同线程中的计算,并且无法保证可能运行的顺序。有没有办法保证订单而不阻塞?

最佳答案

用于推导的 Scala 是“容器类型”(在本例中为 future )上的 flatMap 和 map 调用组合的语法糖,因此您上面的代码等同于:

comp1.flatMap{ comp1Result => comp2 }

此处花括号内的计算仅在 comp1 完成并返回成功结果后发生(在失败的情况下,不会执行内部计算)。

如果您如问题所示在 for comprehension 之外定义 comp2,那么您将开始该计算(您只是忽略结果,直到您在 for comprehension 内),但是如果您仅在 for comprehension 内定义它,那么除非并且直到 comp1 成功完成,否则它不会被启动。因此,尝试按如下方式重新调整代码:
val comp1 = Future { ... } // or you could put this construction inside the for as well
for {
  comp1Result <- comp1
  comp2Result <- Future { ... } // Only start the computation here
  comp3Result <- Future { ... } // etc. for as many such computations as you need
} yield { ... }

其他替代方法是将 comp2 声明为惰性 val(因此实际上不会对其进行评估 - 开始计算 - 直到它被引用),或声明为 lambda(例如 val comp2 = () => Future { ... } )并使用以下行调用它
  comp2Result <- comp2()

里面的理解。

关于scala - Scala 序列中的多个 Future,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30542526/

10-15 18:47