Scala Future阻止变换?

时间:2017-12-20 16:25:15

标签: scala future executioncontext

我有以下测试代码段:

import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration
import scala.util.Success

import scala.concurrent.ExecutionContext.Implicits.global

object FutureAndThen extends App {

  val future = Future {
    println("Started initial Future")
    10
  } andThen { case Success(value) =>
    println("Started callback")
    Thread.sleep(5000)
    println(s"Finished callback: value = $value")
  } map { x =>
    println("Chained transformation")
    x * 2
  }

  println(Await.result(future, Duration.Inf))

}

它产生以下输出:

Started initial Future
Started callback
Finished callback: value = 10
Chained transformation
20

我希望andThen回调可以异步执行。但实际执行是下一个:

  1. 执行原创未来
  2. 执行异步回调
  3. 运行转换(map
  4. 起初我认为问题出在ExecutionContext,它决定在单线程中运行所有这些操作。我将其更改为使用自定义ExecutionContext

    implicit val ctx = ExecutionContext.fromExecutor(
      (command: Runnable) => new Thread(command).start()
    )
    

    结果是一样的。你能告诉我我错过了什么吗?

1 个答案:

答案 0 :(得分:2)

Future.andThen实际记录了此行为:

  

将副作用函数应用于此未来的结果,并返回    这个未来的结果是一个 新的未来 。   
  
此方法允许 强制执行 指定的顺序 执行回调。

这意味着mapandThen内的计算完成之前不会开始工作。如果这不是您想要的,则必须在原始map上致电Future。然后您可以使用onComplete代替andThen,因此代码会变成这样:

  val future = Future {
    println("Started initial Future")
    10
  }

  future onComplete { case Success(value) =>
    println("Started callback")
    Thread.sleep(2000)
    println(s"Finished callback: value = $value")
  }

  val f2 = future map { x =>
    println("Chained transformation")
    x * 2
  }

  println(Await.result(f2, Duration.Inf))

P.S。 AFAIK没有可以与方法链接一起使用的标准onComplete等价物,我认为这是设计使得通过阅读代码更容易预测行为。目前,您可以使用一个简单的规则:如果它是链接的 - 它将在以后执行。