等待另一个未来结束返回功能



假设我有一个函数func1,需要用两个整数返回Future。两个值中的每个值都由独立期货返回,例如:

def f1 = Future { 1 }
def f2 = Future { 2 }
def func1 : Future[(Int,Int)] = {
    val future1 = f1
    future1.map { result1 =>
       result1 * 10
    }
    val future2 = f2
    future2.map { result2 =>
       result2 * 20
    }
} 

我需要future1等到future2结束(或VICE反之亦然(才能将两个结果返回为(Int,Int)。如何完成?

这正是期货上的zip方法:

val futurePair: Future[(Int, Int)] = future1.zip(future2)

请注意,如果您之前没有实例化期货(例如,如果future1future2def s,而不是val s(,则这将平行运行两个计算,而f表示理解(或flatMap(将等待启动第二个之前要成功的第一个。

a for -comprehension是最好的选择:

scala> import scala.concurrent.Future
import scala.concurrent.Future
scala> import concurrent.ExecutionContext.Implicits.global
import concurrent.ExecutionContext.Implicits.global
scala> def f1 = Future{1}
f1: scala.concurrent.Future[Int]
scala> def f2 = Future{2}
f2: scala.concurrent.Future[Int]
scala> for {result1 <- f1; result2 <- f2} yield (result1 * 10, result2 * 20)
res0: scala.concurrent.Future[(Int, Int)] = scala.concurrent.impl.Promise$DefaultPromise@71f67a79

更多信息可以在此处和此处找到。

注意:这将按顺序运行两个Future s,而Cyrille Corpet的解决方案将并行运行。

您可以对已经开始这样启动的期货进行坦白:

val f1: Future[Int] = ???
val f2: Future[Int] = ???
val f3: Future[Int] = ???
val futureInts: Future[(Int, Int, Int)] = for {
  result1 <- f1
  result2 <- f2
  result3 <- f3
} yield (result1, result2, result3)

如果将期货分配给lazy val S或defs,则这是行不通的,因为期货将无法启动(如果您在理解中启动期货,那么它们将被顺序执行(。这是启动它们的示例,然后用for等待它们。

示例:

val f1: Future[Int] = Future {
  println("starting f1")
  Thread.sleep(1000)
  1
}
val f2: Future[Int] = Future {
  println("starting f2")
  Thread.sleep(3000)
  2
}
val f3: Future[Int] = Future {
  println("starting f3")
  Thread.sleep(2000)
  3
}
val futureInts: Future[(Int, Int, Int)] = for {
  result1 <- f1
  result2 <- f2
  result3 <- f3
} yield (result1, result2, result3)
futureInts.map {
  case tuple => println(tuple)
}

输出:

starting f1 // These first 
starting f3 // threes statements
starting f2 // happen right away.
(1,2,2)     // Then this prints a three seconds later

在您的情况下,您可以这样做:

def func1 : Future[(Int,Int)] = {
  // Start futures
  val future1 = f1.map(_ * 10)
  val future2 = f2.map(_ * 20)
  // Wait for both futures, and return a tuple
  for {
    result1 <- future1
    result2 <- future2
  } yield (result1, result2)
}

最新更新