【问题标题】:Scala futures basicsScala 期货基础知识
【发布时间】:2015-11-21 11:00:01
【问题描述】:

我在 Scala 中有以下代码:

case class Water(temp: Int)

case class Milk(temp: Int)

def heatWaterFor(minutes: Int, water: Water) = Future {
  Thread.sleep(1000)
  Water(82)
}

def boilMilkFor(minutes: Int, milk: Milk) = Future {
  Thread.sleep(1000)
  Milk(90)
}

def frothMilk(hotwater: Water, hotmilk: Milk) = Future {
  Thread.sleep(1000)
  hotmilk
}

val start = System.currentTimeMillis()

val milkMaker = for {
   water <- heatWaterFor(10, Water(10))
   milk <- boilMilkFor(5, Milk(10))
   frothed = frothMilk(water, milk)
   hotMilk <- frothed
 } yield (hotMilk)

Await.ready(milkMaker, Duration.Inf)
val end = System.currentTimeMillis() - start
println(milkMaker.value + " , Time taken: "+((end/1000))+" seconds.")

我的意图是并行化heatWaterFor(...)boilMilkFor(...),因为它们是独立的。但我觉得上面的代码是顺序的,根本没有利用期货的力量。显然,运行需要 3000 毫秒(这是一个额外的证明)。

我在这里缺少什么基本的东西?

【问题讨论】:

    标签: scala asynchronous concurrency promise future


    【解决方案1】:

    for 表达式被简化为一系列mapflatMapwithFilter 操作。您的特定 for 表达式被简化为这样的:

    heatWaterFor(10, Water(10))
            .flatMap(water => boilMilkFor(5, Milk(10))
                                 .flatMap(milk => frothMilk(water, milk))
    

    正如您在此处看到的,下一个 future 的执行是在前一个 future 完成时开始的。因此,如果您想并行执行它们,则需要执行以下操作:

    val heatWater = heatWaterFor(10, Water(10))
    val boilMilk = boilMilkFor(5, Milk(10))
    
    val milkMaker = for {
       water <- heatWater
       milk <- boilMilk
       hotMilk <- frothMilk(water, milk)
    } yield (hotMilk)
    

    这将同时启动heatWaterForboilMilkFor,然后在这两个都完成后启动frothMilk(因为这取决于其他两个期货的结果)。

    【讨论】:

      【解决方案2】:

      我猜你正在关注:http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html。最后它提到了为什么这段代码是顺序的以及如何并行化它(Last code sn-p)。

      【讨论】:

      • 您介意在此处发布相关代码吗?仅链接的答案在 SO 中不受欢迎。
      • 点了,但是 marstran 已经在他的答案中发布了代码,所以我将不再发布它。
      【解决方案3】:

      检查this answer

      简而言之,当您像这样使用for 时,您的每个变量(watermilkfrothed)都会在之前的准备就绪时开始计算。这允许在以后的评估中使用先前评估的结果,但它会使计算顺序化。

      另外(不相关)您创建期货的方法(heatWaterFor 等)不使用参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-16
        • 2018-05-25
        • 2014-11-28
        • 2014-02-14
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多