[英]Flaky onSuccess of Future.sequence
我写了这个方法:
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)”,我无法弄清楚为什么它没有按预期工作。
试试这个,
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
确实完成了,那么它就会打印出来。 但这并不总是发生
应用程序在未来完成之前退出。
你需要阻塞直到未来完成。 这可以通过多种方式实现,包括更改 ExecutionContext、实例化新的 ThreadPool、Thread.sleep 等,或使用scala.concurrent.Await
方法
代码最简单的方法是使用Await.ready
。 这会在指定的时间内阻止future
。 在下面修改后的代码中,应用程序在退出前等待 5 秒。
还要注意,额外的 import 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.