Skip to content

Part VII: 非同期プログラミング

概要

本章では、Scala の Future と Promise を使った非同期プログラミングを学びます。


Future の基本

import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.ExecutionContext.Implicits.global

val future: Future[Int] = Future {
  Thread.sleep(1000)
  42
}

// コールバック
future.onComplete {
  case Success(value) => println(s"Result: $value")
  case Failure(e) => println(s"Error: ${e.getMessage}")
}

Future の合成

map と flatMap

val f1: Future[Int] = Future(10)
val f2: Future[Int] = Future(20)

// map: 結果を変換
val doubled: Future[Int] = f1.map(_ * 2)

// flatMap: Future を連結
val sum: Future[Int] = f1.flatMap(a => f2.map(b => a + b))

for 内包表記

val result: Future[Int] = for
  a <- Future(10)
  b <- Future(20)
  c <- Future(30)
yield a + b + c

並列実行

import scala.concurrent.{Future, Await}
import scala.concurrent.duration._

// 並列に実行される
val futures = List(
  Future { Thread.sleep(1000); "A" },
  Future { Thread.sleep(1000); "B" },
  Future { Thread.sleep(1000); "C" }
)

// 全てを待機
val results: Future[List[String]] = Future.sequence(futures)
val values = Await.result(results, 5.seconds)
// List("A", "B", "C") - 約 1 秒で完了

Promise

import scala.concurrent.Promise

val promise = Promise[Int]()
val future = promise.future

// 別のスレッドで完了
Future {
  Thread.sleep(1000)
  promise.success(42)
}

future.onComplete {
  case Success(v) => println(s"Got: $v")
  case Failure(e) => println(s"Failed: $e")
}

エラーハンドリング

val future = Future {
  throw new RuntimeException("Error!")
}

// recover: 失敗時のフォールバック
val recovered = future.recover {
  case _: RuntimeException => 0
}

// recoverWith: 失敗時に別の Future
val recoveredWith = future.recoverWith {
  case _: RuntimeException => Future.successful(0)
}

次のステップ

Part VIII では、MapReduce パターンと並列コレクションを学びます。