ScalaのFutureの使い方メモ

| Comments

Futureは非同期に行いたい処理(時間かかる系・ファイルIOや通信など、外部システムに処理を投げる系)を非同期に行うことができるAPIです。

参考サイト

宣言の仕方

1
2
3
4
val firstOccurence: Future[Int] = future {
  val source = scala.io.Source.fromFile("myText.txt")
  source.toSeq.indexOfSlice("myKeyword")
}

ここではファイル操作のシステムに処理を投げ、結果をFuture[Int]という入れ物に入れてもらうと宣言している。

ちなみに、Scala2.11〜はfutureメソッドの代わりにFutureを使うことが推奨されてるらしい。

使い方

普通は、処理を外部に投げた後に、処理の結果(先の例だとInt型のデータ)を使いたいことがほとんどだと思われる。

取り出し方法は二通りあって、

  • 処理が完了した時点でcallback関数を実行する(Non-Blocking)
  • 処理が完了するまで同一スレッドで待機させる(Blocking)

Webアプリケーションなどのサーバーサイドの実装をしたい場合は、Non-Blockingだと一スレッドで完結しないのでたぶん使いづらいんだと思う。

例えば、ある時間のかかる処理を依頼するPOSTリクエストを投げた時には、一度そのリクエストを受け取ったというメッセージだけ返して、裏で非同期に処理させて、結果は別途通知する、という仕組みになるんだろうな、と思っています。

Non-Blockingの場合

1
2
3
4
f onComplete {
  case Success(posts) => callback(posts)
  case Failure(t) => println("エラーが発生した: " + t.getMessage)
}

成功ならFuture[T]のT型が、失敗ならThrowable型が返ってきます。

成功時だけ取ってきたい場合は、

1
2
3
f onSuccess {
  case posts => callback(posts)
}

などとします。

Blockingの場合

※これをやると実質非同期にならないのでオススメしない。

1
2
3
4
5
//Future[T]のT型が返ってくる。失敗なら例外[Throwable]が投げられます。
Await.result(f, Duration.Inf)

//終わった結果を取得する。値はThrowaleかTでパターンマッチして処理する。
Await.ready(f, Duration.Inf)

ちなみに、Duration.InfはAwaitする期間を表す。今回の例は「無限に待つ」の意。 他にも10 nanosとか使える。

Comments