为了理解 - 按顺序执行期货

时间:2016-06-02 16:00:49

标签: scala

如果我有以下理解,期货将按顺序执行:f1f2f3

   val f = for {
      r1 <- f1
      r2 <- f2(r1)
      r3 <- f3(r2)
    } yield r3

然而,对于这一个,所有的期货都是同时开始的:

  val f = for {
      r1 <- f1
      r2 <- f2
      r3 <- f3
    } yield ...

如何执行订单?(我希望此执行顺序f1f2f3

3 个答案:

答案 0 :(得分:3)

f1f2f3是多么重要:未来将在创建后立即开始执行。在第一种情况下,f2(r1)必须是函数返回未来,因此将在调用函数时开始执行,这在r1可用时发生。

如果第二种情况相同(f2是一个函数),那么行为将与第一种情况相同,您的期货将按顺序执行,一个接一个地执行。

但是如果您在for之外创建期货,只需将它们分配给变量f1f2f3,那么当您进入理解时,他们已经正在运行。

答案 1 :(得分:2)

Future是热切的构造,也就是说,一旦创建,你就无法决定它们何时被处理。如果当你试图在for-comprehension中使用它时Future已经存在,那么你已经失去了对它的执行顺序进行排序的能力。

如果要对接受Future参数的方法强制执行排序,那么您需要将评估包装在thunk中:

def foo(ft: => Future[Thing], f2: => Future[Thing]): Future[Other] = for{
  r1 <- ft
  r2 <- f2
} yield something(r1, r2)

另一方面,如果您想在方法正文中定义Future,则代替val使用def

def foo() ={
  def f1 = Future{ code here... }
  def f2 = Future{ code here... }
  for{
    r1 <- f1
    r2 <- f2
  } yield something(r1, r2)

答案 2 :(得分:2)

执行期货以进行理解是默认行为。当很少有任务被并行处理而没有任何阻塞时,这是很好的。

但是如果你想保留处理顺序,你必须采取行动:

  • 将第一个任务的结果发送到第二个任务,例如
  • 使用andThen运算符

    val allposts = mutable.Set[String]()    
    Future {
      session.getRecentPosts
    } andThen {
      posts => allposts ++= posts
    } andThen {
      posts =>
      clearAll()
      for (post <- allposts) render(post)
    }