我写了这个方法:
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)"只是偶尔一次,我无法弄清楚为什么它不能按预期工作。
答案 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)