doilux’s tech blog

ITに関する備忘録。 DDP : http://doiluxng.hatenablog.com/entry/2018/01/01/195409

scala.concurrent.Futureのあれこれメモ

Scalaを初めて、scala.concurrent.Futureに慣れてなかったのであれこれメモ

ただ実行する。

scala> Future {
     |     Thread.sleep(3000)
     |     println("hey!!")
     | }
res6: scala.concurrent.Future[Unit] = Future(<not completed>)

scala> hey!!

Futureの戻り値はFuture[Unit]になる。

戻り値を取得する。Successになってたら取得できる。

scala> val f = Future {
     |     Thread.sleep(10000)
     |     "hey!!"
     | }
f: scala.concurrent.Future[String] = Future(<not completed>)

scala> f
res13: scala.concurrent.Future[String] = Future(<not completed>)

scala> f.value.get.get
java.util.NoSuchElementException: None.get
  at scala.None$.get(Option.scala:349)
  at scala.None$.get(Option.scala:347)
  ... 28 elided

scala> f
res15: scala.concurrent.Future[String] = Future(Success(hey!!))

scala> f.value.get.get
res16: String = hey!!

複数のFutureをまとめる。

scala> val f1 = Future {
     |     Thread.sleep(3000)
     |     "hey!!"
     | }
f1: scala.concurrent.Future[String] = Future(<not completed>)

scala> val f2 = Future {
     |     Thread.sleep(3000)
     |     "what's up?"
     | }
f2: scala.concurrent.Future[String] = Future(<not completed>)

scala> val i = for {
     |     r1 <- f1
     |     r2 <- f2
     | } yield r1+r2
i: scala.concurrent.Future[String] = Future(<not completed>)

scala> i.value.get.get
res18: String = hey!!what's up?

Future[String]とかをFuture[Unit]にする(戻り値を捨てる)

scala> val f = Future {
     |     Thread.sleep(3000)
     |     val message = "hey!!"
     |     println(message)
     |     message
     | }
f: scala.concurrent.Future[String] = Future(<not completed>)

scala> hey!!


scala> val r = for {
     |     r <- f
     | } yield {}
r: scala.concurrent.Future[Unit] = Future(<not completed>)

リストでつかう。こうするとSeq[Future[Int]]になる。

scala> def len(input: String): Future[Int] = {
     |     Future {
     |         Thread.sleep(3000)
     |         input.length
     |     }
     | }
len: (input: String)scala.concurrent.Future[Int]

scala> val l = Seq("hoge", "fuga", "piyo")
l: Seq[String] = List(hoge, fuga, piyo)

scala> val r = l.map(len(_))
r: Seq[scala.concurrent.Future[Int]] = List(Future(<not completed>), Future(<not completed>), Future(<not completed>))

Future[Seq[Int]]にしたいときはFuture.sequenceを使う

scala> val r2 = Future.sequence(r)
r2: scala.concurrent.Future[Seq[Int]] = Future(<not completed>)