Scala等待期货序列 [英] Scala waiting for sequence of futures
问题描述
我希望像下面这样的代码可以等待两种期货,但事实并非如此.
I was hoping code like follows would wait for both futures, but it does not.
object Fiddle {
val f1 = Future {
throw new Throwable("baaa") // emulating a future that bumped into an exception
}
val f2 = Future {
Thread.sleep(3000L) // emulating a future that takes a bit longer to complete
2
}
val lf = List(f1, f2) // in the general case, this would be a dynamically sized list
val seq = Future.sequence(lf)
seq.onComplete {
_ => lf.foreach(f => println(f.isCompleted))
}
}
val a = FuturesSequence
我以为seq.onComplete
会等到它们全部完成才完成本身,但事实并非如此.结果为:
I assumed seq.onComplete
would wait for them all to complete before completing itself, but not so; it results in:
true
false
在scala.concurrent.Future的源代码中,
.sequence
有点难以理解,我想知道如何实现一个并行处理,以等待(动态大小的)序列的所有原始将来,否则可能是问题所在在这里.
.sequence
was a bit hard to follow in the source of scala.concurrent.Future, I wonder how I would implement a parallel that waits for all original futures of a (dynamically sized) sequence, or what might be the problem here.
相关问题:推荐答案
等待所有结果(失败与否)的一种常用方法是将失败提升"到未来内部的新表示中,以便所有未来都完成一些结果(尽管它们可能会以表示故障的结果来完成).一种自然的获取方法是提升到 One common approach to waiting for all results (failed or not) is to "lift" failures into a new representation inside the future, so that all futures complete with some result (although they may complete with a result that represents failure). One natural way to get that is lifting to a Twitter对期货的实施提供了 Twitter's implementation of futures provides a 现在 Now 因此,假设执行上下文当然隐式可用,则用于等待一系列期货的所有原始期货的通用解决方案可能如下所示. And so, a generic solution for waiting on all original futures of a sequence of futures may look as follows, assuming an execution context is of course implicitly available. 这篇关于Scala等待期货序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!Try
.Try
.liftToTry
method that makes this trivial, but you can do something similar with the standard library's implementation:import scala.util.{ Failure, Success, Try }
val lifted: List[Future[Try[Int]]] = List(f1, f2).map(
_.map(Success(_)).recover { case t => Failure(t) }
)
Future.sequence(lifted)
将在每个将来完成时完成,并且将代表使用Try
的成功和失败.Future.sequence(lifted)
will be completed when every future is completed, and will represent successes and failures using Try
. import scala.util.{ Failure, Success, Try }
private def lift[T](futures: Seq[Future[T]]) =
futures.map(_.map { Success(_) }.recover { case t => Failure(t) })
def waitAll[T](futures: Seq[Future[T]]) =
Future.sequence(lift(futures)) // having neutralized exception completions through the lifting, .sequence can now be used
waitAll(SeqOfFutures).map {
// do whatever with the completed futures
}