LoginSignup
3

More than 3 years have passed since last update.

Scalaでfor式とFutureを一緒に使うときは注意!!

Posted at

結論

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 ミリ秒になる。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3