A
Future
is a placeholder object for a value that may not yet exist. By default, futures and promises are non-blocking, making use of callbacks instead of typical blocking operations. Blocking is still possible - for cases where it is absolutely necessary, futures can be blocked on (although this is discouraged).Future and Promises revolve around
ExecutionContext
s, responsible for executing computations.Future
Scala’s
Future[T]
, residing in the scala.concurrent
package, is a container type, representing a computation that is supposed toeventually result in a value of type T
.Future
is a write-once container – after a future has been completed, it is effectively immutable. Also, the Future
type only provides an interface for reading the value to be computed. The task of writing the computed value is achieved via a Promise
.An
ExecutionContext
is something that can execute our future, and you can think of it as something like a thread pool.The simplest way to create a future object is to invoke the
future
method which starts an asynchronous computation and returns a future holding the result of that computation. The result becomes available once the future completes.import scala.concurrent._
import ExecutionContext.Implicits.global
val session = socialNetwork.createSessionFor("user", credentials)
val f: Future[List[Friend]] = Future {
session.getFriends()
}
f onComplete {
case Success(posts) => for (post <- posts) println(post)
case Failure(t) => println("An error has occured: " + t.getMessage)
}
Callback
If the future has already been completed when registering the callback, then the callback may either be executed asynchronously, or sequentially on the same thread.
Callbacks for futures are partial functions. You can pass a callback to the
Callbacks for futures are partial functions. You can pass a callback to the
onSuccess
method. It will only be called if the Future
completes successfully, and if so, it receives the computed value as its input. Usually, it’s better to combine these two and register a completion callback that will handle both cases. The input parameter for that callback is a Try
Since callback requires the value in the future to be available, it can only be called after the future is completed. However, there is no guarantee it will be called by the thread that completed the future or the thread which created the callback. Instead, the callback is executed by some thread, at some time after the future object is completed. We say that the callback is executed eventually.
Furthermore, the order in which the callbacks are executed is not predefined, even between different runs of the same application. In fact, the callbacks may not be called sequentially one after the other, but may concurrently execute at the same time.
Composing futures
Future
is a container type, made it possible for you to map them, flat map them, or use them in for comprehensions .
val temperatureOkay: Future[Boolean] = heatWaterFuture(Water(25))
.map { water =>
println("we're in the future!")
(80 to 85).contains(water.temperature)
}
That mapping function gets executed as soon as your
Future[Water]
instance has completed successfully. If your instance of Future[Water]
fails, what’s taking place in the function you passed to map
will never happen. Instead, the result of calling map
will be a Future[Boolean]
containing a Failure
.
If the computation of one
Future
depends on the result of another, you’ll likely want to resort to flatMap
to avoid a deeply nested structure of futures.
val flatFuture: Future[Boolean] = heatWaterFuture(Water(25))
.flatMap {
water => temperatureOkayFuture(water)
}
val flatFuture: Future[Boolean] = for {
heatedWater <- heatWaterFuture(Water(25))
okay <- temperatureOkayFuture(heatedWater)
} yield okay
Instead of calling
flatMap
, you’ll usually want to write a for comprehension, which is essentially the same, but reads a lot clearer. If you do use Futures be careful to not close over the session object.The session might get closed outside the Future. Instead create the session inside the Future and close it after the Future completes, e.g. using andThen.
Reference:
http://docs.scala-lang.org/overviews/core/futures.html
http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html
http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html
No comments:
Post a Comment