Scala 同步2个或更多未来的计算

Scala 同步2个或更多未来的计算,scala,parallel-processing,future,Scala,Parallel Processing,Future,我发现我不知道如何同步计算2个或更多的Futures: val fs = List(1, 2, 3) map { x => Future { /* some computation depending on x... */ } } fs(0) onComplete { case Success(x) => fs(1) onComplete { case Success(x) => fs(2) onComplete .... } 这

我发现我不知道如何同步计算2个或更多的
Futures

val fs = List(1, 2, 3) map { x => Future { /* some computation depending on x... */ } }
fs(0) onComplete {
  case Success(x) => 
    fs(1) onComplete { 
      case Success(x) => 
        fs(2) onComplete ....
}
这看起来不合理


我想从
fs
中获取所有值。如何执行此操作?

在未来的伴生对象中,有一个用于此操作的帮助器方法:

val fs: List[Future[Int]] = List(1, 2, 3) map { x => Future { /* some computation depending on x... */ } }
val allFs: Future[List[Int]] = Future.sequence(fs)

您可以使用
Future.sequence
List[Future]
转换为
Future[List]

val fs = List(1, 2, 3) map { x => Future(x * x) }
val f = Future.sequence(fs)
f.onComplete(println(_))

将打印
成功(列表(1、4、9))
使用
未来。遍历

val inList = List(1, 2, 3)
val fs = Future.traverse(inList) { x =>
  Future {
    /* some computation depending on x... */
  }
}

fs onSuccess { case outList => 
  ...
}
如果任何元素出现故障,则此操作将失败

如果您想要所有的结果,不管是失败还是成功,那么最好的方法是
恢复它们,将结果包装在
Try
的实例中:

def asyncFunc(i: Int): Future[String] = ...

val inList = List(1, 2, 3)
val rawResults = inList.map(asyncFunc)
val recoveredResults = rawResults.map(Success(_)).recover(case x => Failure(x))

val completedResults = Future.sequence(recoveredResults)

completedResults onSuccess { case outList =>
  outList map {
    case Success(s) => ...
    case Failure(t) => ...
  }
}
提示:如果您经常做这类事情,通常更容易确保所有的异步方法通过
Future[Try[T]]
的实例成功完成,而不是在
Future
中嵌入任何错误

大概是这样的:

def slowFunc(i: Int): String = ...
def asyncFunc(i: Int): Future[Try[String]] = Future { Try { slowFunc(i) } }

val inList = List(1, 2, 3)
val results = Future.traverse(inList)(asyncFunc)

results onSuccess { case outList =>
  outList map {
    case Success(s) => ...
    case Failure(t) => ...
  }
}

您还可以使用
for
语句来实现这一点

val f1 : Future[A] = Future { /* whatever */ }
val f2 : Future[B] = Future { /* whatever */ }
val results : Future[(A,B)] = for {
   f1Result <- f1
   f2Result <- f2
} yield(f1Result, f2Result)
val f1:Future[A]=Future{/*whatever*/}
val f2:Future[B]=未来{/*无论什么*/}
val结果:未来[(A,B)]=对于{

f1Result有一个技巧可以避免在外部声明未来以供理解,我在这里已经描述过:注意“onComplete”,其中的代码(
println()
)不会在主线程上运行。在某些用例中可能会出现问题。