【问题标题】:How can you compose dependent futures in Scala so that all but one run in parallel?你如何在 Scala 中组合依赖的期货,以便除一个之外的所有期货都并行运行?
【发布时间】:2017-10-24 02:29:45
【问题描述】:

例如你可以这样做:

Future(/* A */).flatMap(_ => Future(/* B */).flatMap(_ => Future(/* C */)))

这里 B 依赖于 A 来完成,有没有一种干净的方式来组合期货,以便 C 依赖于 A 和 B 来完成并且 A 和 B 可以并行运行?

【问题讨论】:

    标签: scala parallel-processing future flatmap


    【解决方案1】:

    我认为您正在寻找的是Future.sequence 方法,它允许您将Futures 的序列减少为单个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)
    

    其中一次运行的输出是:

    从睡眠 1287 开始 B
    从睡眠 550 开始 A
    A之后
    B 之后
    以睡眠 100 启动 C1837
    C1837 之后

    如果你也想“快速失败”,可以考虑How to wait for several Futures的更复杂的答案

    【讨论】:

      【解决方案2】:

      Future(A).zipWith(Future(B))((_,_) => C)

      【讨论】:

        【解决方案3】:

        for yield 是这样做的干净方式,它等于flatMap,例如:

        val futureA = Future {
          // do something
        }
        val futureB = Future {
          // do something
        }
        for {
        _ <- futureA
        _ <- futureB
        } yield Future {
          /* C */
        }
        

        初始futureAfutureBfor comprehensive之前,它们将并行运行。

        【讨论】:

        • 我需要 A 和 B 并行运行,这将按顺序运行它们
        • @goodOldFashioned 如果您在 for 理解中启动它们,这只会按顺序运行它们。如果 futureAfutureB 类似于 Future[_] 而不是 () =&gt; Future[_] 那么这将正常工作
        猜你喜欢
        • 2015-08-25
        • 1970-01-01
        • 1970-01-01
        • 2015-08-06
        • 1970-01-01
        • 2019-06-17
        • 2016-05-02
        • 1970-01-01
        • 2018-01-25
        相关资源
        最近更新 更多