scala的Future.sequence方法的行为

时间:2015-01-21 22:29:37

标签: scala sequence future

我写了这个方法:

import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }

object FuturesSequence extends App {
  val f1 = future {
    1
  }

  val f2 = future {
    2
  }

  val lf = List(f1, f2)

  val seq = Future.sequence(lf)

  seq.onSuccess {
    case l => println(l)
  }
}

我期待Future.sequence将List [Future]收集到Future [List]中然后等待每个期货(在我的情况下为f1和f2)完成,然后在我的Future [List] seq上调用onSuccess情况下。

但经过多次运行此代码后,它会打印" List(1,2)"只是偶尔一次,我无法弄清楚为什么它不能按预期工作。

2 个答案:

答案 0 :(得分:3)

尝试一次,

import scala.concurrent._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }

object FuturesSequence extends App {
  implicit val exec = ExecutionContext.fromExecutor(Executors.newCachedThreadPool)
  val f1 = future {
    1
  }

  val f2 = future {
    2
  }

  val lf = List(f1, f2)

  val seq = Future.sequence(lf)

  seq.onSuccess {
    case l => println(l)
  }
}

这将始终打印List(1,2)。原因很简单,上面的exec是线程的ExecutionContext(不是守护程序线程),在你的例子中,ExecutionContext是默认的隐含的ExecutionContext.Implicits.global,包含守护程序线程。

因此,作为守护进程,该进程不会等待seq将来完成并终止。如果完全seq确实完成,则打印出来。但这并不总是发生

答案 1 :(得分:3)

应用程序在未来完成之前退出。

You need to block until the future has completed。这可以通过多种方式实现,包括更改ExecutionContext,实例化新的ThreadPool,Thread.sleep等,或者使用scala.concurrent.Await上的方法

代码的最简单方法是使用Await.ready。这将在future上阻止指定的时间。在下面的修改代码中,应用程序在退出前等待5秒钟。

另请注意,额外导入scala.concurrent.duration,以便我们指定等待的时间。

import scala.concurrent._
import scala.concurrent.duration._
import java.util.concurrent.Executors
import scala.util.{ Success, Failure }

object FuturesSequence extends App {
  val f1 = future {
    1
  }

  val f2 = future {
    2
  }

  val lf = List(f1, f2)

  val seq = Future.sequence(lf)

  seq.onSuccess {
    case l => println(l)
  }

  Await.ready(seq, 5 seconds)
}

使用Await.result代替,您也可以跳过onSuccess方法,因为它会将结果列表返回给您。

示例:

val seq: List[Int] = Await.result(Future.sequence(lf), 5 seconds)
println(seq)