はじめに
- バッチ処理などでScalaの複数のFutureが全て処理を終わったらステータスを更新したいケースなど結構あるので実装メモ。
実装
-
Await.ready
とFuture.sequence
を用いて簡単に書ける。
import scala.concurrent.duration.DurationInt
import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor, Future}
object Main extends App {
implicit val ec: ExecutionContextExecutor = ExecutionContext.global
println("Start.")
val f1 = Future { Thread.sleep(1000); 1 }
val f2 = Future { Thread.sleep(2000); 1 }
val f3 = Future { Thread.sleep(3000); 1 }
Await.ready(Future.sequence(Seq(f1, f2, f3)), 10.seconds)
println("Done.")
}
実行結果
- 3秒くらい待つと終了するので想定通りに動いている。
Start.
Done.
- Awaitの待ち時間を10秒->2秒に変更して実行してみるとタイムアウト例外が発生して想定通り。
Start.
Exception in thread "main" java.util.concurrent.TimeoutException: Future timed out after [2 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.tryAwait0(Promise.scala:212)
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:104)
at scala.concurrent.Await$.$anonfun$ready$1(package.scala:174)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:62)
at scala.concurrent.Await$.ready(package.scala:124)
at Main$.delayedEndpoint$Main$1(Main.scala:17)
at Main$delayedInit$body.apply(Main.scala:9)
at scala.Function0.apply$mcV$sp(Function0.scala:39)
at scala.Function0.apply$mcV$sp$(Function0.scala:39)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
at scala.App.$anonfun$main$1(App.scala:73)
at scala.App.$anonfun$main$1$adapted(App.scala:73)
at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:553)
at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:551)
at scala.collection.AbstractIterable.foreach(Iterable.scala:920)
at scala.App.main(App.scala:73)
at scala.App.main$(App.scala:71)
at Main$.main(Main.scala:9)
at Main.main(Main.scala)