[英]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.