您如何在 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 */
}
初始futureA
和futureB
在for comprehensive
之前,它们将运行并行。
Future(A).zipWith(Future(B))((_,_) => C)
例如你可以这样做:
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 */
}
初始futureA
和futureB
在for comprehensive
之前,它们将运行并行。
Future(A).zipWith(Future(B))((_,_) => C)