結論
for式は変換を直列化するので、Futureをfor式の中で使うと並列化されない
実装から理解する
以下の二点を実装し、実行時間を比較しながら確認していく
- for式の中でFutureを使った場合
- for式の外でFutureを使った場合
for式の中でFutureを使った場合
package hoge
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
object test {
def main(args: Array[String]): Unit = {
val start = System.currentTimeMillis
val result = for {
h <- Future{Thread.sleep(1000); "hello "}
s <- Future{Thread.sleep(1000); "scala"}
}yield h + s
Await.ready(result,Duration.Inf)
println(result)
println("処理時間: " + (System.currentTimeMillis - start) + " ミリ秒")
}
}
//Future(Success(hello scala))
//処理時間: 2620 ミリ秒
for式の中で直列化されるので、Future{Thread.sleep(1000); "hello "}
が終わった後に、
Future{Thread.sleep(1000); "scala"}
が呼ばれる。
なので、結果的に処理時間: 2620 ミリ秒になる。
for式の外でFutureを使った場合
package hoge
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
object test {
def main(args: Array[String]): Unit = {
val start = System.currentTimeMillis
val f1 = Future{Thread.sleep(1000); "hello "}
val f2 = Future{Thread.sleep(1000); "scala"}
Await.ready(f1,Duration.Inf)
Await.ready(f2,Duration.Inf)
val result = for {
h <- f1
s <- f2
}yield h + s
println(result)
println("処理時間: " + (System.currentTimeMillis - start) + " ミリ秒")
}
}
//Future(Success(hello scala))
//処理時間: 1522 ミリ秒
以下のFutureはmainスレッドと別のスレッドで動くため、非同期に実行される。
val f1 = Future{Thread.sleep(1000); "hello "}
val f2 = Future{Thread.sleep(1000); "scala"}
for式の中では、別スレッドで実行されたFutureの結果を用いて処理が行われる。
なので、結果的に処理時間: 1522 ミリ秒になる。