some notes on scala future, includes:
- future
- executor context
- await future result
- callback
- recover
future
import java.time._
import scala.concurrent._
import ExecutionContext.Implicits.global
Future {
Thread.sleep(10000)
println(s"This is the future at ${LocalTime.now}")
}
println(s"This is the present at ${LocalTime.now}")
executor context
future need a new thread to execute it task. import ExecutionContext.Implicits.global
is a implicit threadpool.
await for future result
// for 10.seconds conversion
import scala.concurrent.duration._
val f = Future { Thread.sleep(10000); 42 }
val result = Await.result(f, Duration.Inf)
// if f throw exception, it will rethrow to Await.result
// use ready() solve this
val f = Future { ... }
Await.ready(f, 10.seconds)
val Some(t) = f.value
// The f.value method returns an Option[Try[T]],
// which is None when the future is not completed
// and Some(t) when it is is
// t is Try type instance
// A Try[T] instance is either a Success(v), where v is a value of type T or a Failure(ex)
val t = Some(t).get
t match {
case Success(v) => println(s"The answer is $v")
case Failure(ex) => println(ex.getMessage)
}
// or
if (t.isSuccess) println(s"The answer is ${t.get}")
callback
val f = Future { Thread.sleep(10000)
if (random() < 0.5) throw new Exception
42
}
f.onComplete {
case Success(v) => println(s"The answer is $v")
case Failure(ex) => println(ex.getMessage)
}
callback hell
val future1 = Future { getData1() }
val future2 = Future { getData2() }
future1 onComplete {
case Success(n1) =>
future2 onComplete {
case Success(n2) => {
val n = n1 + n2
println(s"Result: $n")
}
case Failure(ex) => ...
}
case Failure(ex) => ...
}
// improve
val future1 = Future { getData1() }
val combined = future1.map(n1 => n1 + getData2())
//
val future1 = Future { getData1() }
val future2 = Future { getData2() }
val combined = future1.map(n1 => future2.map(n2 => n1 + n2))
// use for-yield
for (
n1 <- future1
n2 <- future2
) yield n1+n2