SIP 14
There were eight different Future implementations:
java.util.concurrent.Future akka.dispatch.Futurescala.actors.Future scalaz.concurrent.Promisescala.parallel.Future net.liftweb.actor.LAFuturecom.twitter.util.Future ...sff4s
Define ThemFuture and Promise are tied to each other. But they are different!
A Future is a read-handle to a single value that may be available in a specific time frame.
A Promise is a write-handle to a single value (write-once) that should be made available in a specific time-frame.
Akka Futures definitionA Future is a data structure
Used to retrieve of some concurrent operation
This operation is performed by an Actor or a dispatcher directly
The result can be accessed synchronously or asynchronously
Future has States
A Future has three states. Initially it does not have anything, later can be a success or a failure.
Pending => Success / Failure
Execution Context
Futures need ExecutionContext to execute callback and operations
If we have ActorSystem in implicit scope Future will use default dispatcher as ExecutionContext
Simplest Future
import akka.actor.ActorSystemimport akka.dispatch.Future
object SimplestFutureApp extends App { implicit val system = ActorSystem("future") val future = Future { "Hello " + " World" }}
Promise
The other side of Future is a Promise.
Think that the entity that creates a Future is a Requester and the one that can respond back has a Promise.
We hardly use Promise in our code, but it completes the understanding nonetheless!!
Promise Exampleobject PromiseApp extends App { implicit val system = ActorSystem("future") // create a promise val promise = Promise[String]() // get an associated future from that promise val future = promise.future // successfully fulfill that promise promise.success("promises are to be kept") // Extract the value from the Future println(future.value)
}
Composing Futures
Futures are Monadic
There are map and flatMap methods on them
We can therefore compose them monadically and do asynchronous composition!!
Composing Example
import akka.actor.ActorSystemimport akka.dispatch.Future
object CreatingFutureFromAFutureApp extends App { implicit val system = ActorSystem("future")
// Future[String] val future = Future { "Hello " + " World" }
// Futures are monadic so we can transform from Future[String] to Future[Int] val anotherFuture = future map { aString => aString.length }
}
Sync Wait On Future
There is an Await method if we have to wait for a Future to complete.
Always avoid this. Use it as last option. Never block thats the whole point.
Sync Wait Exampleobject SyncWaitOnFuture extends App { implicit val system = ActorSystem("future") implicit val timeout = Timeout(50000 milliseconds)
val future = Future { "Hello " + " World" }
val anotherFuture = future map { aString => aString.length }
// try to avoid this as much as possible val number = Await.result(anotherFuture, timeout.duration) println("String length is " + number)}
Async Wait
Future has several callbacks. They areonComplete: It will either be a Success or a Failure
onSuccess: It will be invoked only when Future is successful
onFailure: It will be invoked only when Future got a Throwable in it.
Async Wait Exampleimport akka.actor.ActorSystemimport akka.dispatch.Future
object AsyncWaitOnFuture extends App { implicit val system = ActorSystem("future")
val future = Future { "Hello " + " World" }
val anotherFuture = future map { aString => aString.length }
anotherFuture onSuccess { case number => println("String length is " + number) }
}
Using Futures
Futures allows us to do a data flow style of programming
We know, there can be a certain type of value in a Future. So, we can do asynchronous composition on that Future.
This will result (yield) a new Future. We do not block as we compose even when we do not have a value yet
Futures Example
We have an identity function that sleeps for 3 seconds
We want make a call to it three times gather their result and sum them
Normal code as expected will take nine seconds :(
With Futures we can do it in three seconds :)
Futures Example...Here is the code for identity function. Followed by creation of three futures.
// creating three futures val future1 = Future { identity(1) } val future2 = Future { identity(2) } val future3 = Future { identity(3) }
def identity(number: Int): Int = { Thread.sleep(3000) number }
Futures Example...Now composing code using flatMap and Map
// composing using map and flatMqp // not concise at all :( val oneFinalFuture = future1 flatMap { result1 => future2 flatMap { result2 => future3 map { result3 => result1 + result2 + result3 } } }
Futures Example...
Now composing code using for expressions
// for expressions are just a sugar. They are really concise :) val finalFuture = for { result1 <- future1 result2 <- future2 result3 <- future3 } yield result1 + result2 + result3
Futures Example...
Now we issue a callback to collect result
finalFuture onSuccess { case sum => println("sum is " + sum) }
Code Samples
https://github.com/knoldus/AkkaKnolX
References
Viktor Klang talk on Akka And Futures at javaZone