【问题标题】:Waiting for another future to end to return a function等待另一个未来结束返回一个函数
【发布时间】:2017-10-03 02:37:43
【问题描述】:

假设我有一个函数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 结束(反之亦然)将两个结果都返回为(Int,Int)。这如何实现?

【问题讨论】:

    标签: scala future


    【解决方案1】:

    这正是期货上的 zip 方法所做的:

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

    请注意,如果您之前没有实例化您的期货(例如,如果 future1future2defs,而不是 vals),这将并行运行两个计算,而 for理解(或flatMap)会等待第一个成功,然后再开始第二个。

    【讨论】:

    • 如果有 3 个或 4 个期货会发生什么?有可能有一个 Tuple4 吗?还是嵌套元组?
    • 它将是嵌套的元组。但是您始终可以使用map 为他们提供您想要的形式。如果你有一个List[Future[Int]],你甚至可以使用静态方法Future.sequence来等待它们全部变成Future[List[Int]]
    • 要解释我所说的使用map的意思,您可以使用future1 zip future2 zip future3 map { case ((a, b), c) => (a, b, c) }
    【解决方案2】:

    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
    

    更多信息可以在herehere找到。

    注意:这将依次运行两个Futures,而Cyrille Corpet's solution 将并行运行它们。

    【讨论】:

    • 这会依次运行 f1 和 f2。另一个答案更好。
    【解决方案3】:

    您可以对已经开始的期货使用 for-comprehension,如下所示:

    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 vals 或defs,那么这将不起作用,因为期货不会启动(如果您在 for 理解中启动期货,那么它们将按顺序执行) .这是一个启动它们的示例,然后使用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)
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多