您如何在 Scala 中组合相关的期货,以便除一个 运行 之外的所有期货并行?

How can you compose dependent futures in Scala so that all but one run in parallel?

例如你可以这样做:

Future(/* A */).flatMap(_ => Future(/* B */).flatMap(_ => Future(/* C */)))

这里 B 依赖于 A 来完成,是否有一种干净的方式来组合期货,以便 C 依赖于 A 和 B 来完成并且 A 和 B 可以 运行 并行?

我认为您正在寻找的是 Future.sequence 方法,它允许您将 Future 的序列减少为单个 Future。这是一个简单的例子:

def createFuture(name: String, sleep: Int): Future[(String, Int)] = {
  Future({
    println(s"Starting $name with sleep $sleep")
    Thread.sleep(sleep)
    println(s"After $name")
    (name, sleep)
  })
}

val rnd = new Random()
val fa = createFuture("A", rnd.nextInt(1000) + 500)
val fb = createFuture("B", rnd.nextInt(1000) + 500)
val ff = Future.sequence(List(fa, fb)).flatMap(l => createFuture("C" + l.map(_._2).sum, 100))
Await.result(ff, Duration.Inf)

其中一次运行的输出是:

Starting B with sleep 1287
Starting A with sleep 550
After A
After B
Starting C1837 with sleep 100
After C1837

如果你也想拥有"fast failure",你可以考虑来自How to wait for several Futures

的更复杂的答案

for yield 是一种干净的方法,它等于 flatMap,例如:

val futureA = Future {
  // do something
}
val futureB = Future {
  // do something
}
for {
_ <- futureA
_ <- futureB
} yield Future {
  /* C */
}

初始futureAfutureBfor comprehensive之前,它们将运行并行。

Future(A).zipWith(Future(B))((_,_) => C)