Futures allow asynchronous and non-blocking operations in Scala. They represent a value that may be available in the future. Promises allow producing values for futures - a promise can be used to complete a future with a value. Futures can be composed using methods like map, flatMap, and recover to build asynchronous workflows. Callbacks allow non-blocking handling of future results.
4. Asynchronous Scala: Promising futures
● Purely functional: whole world could be implemented in a single
functional line
● Functional features
○ Robust
○ Debuggable
○ Predictable
○ Pluggable
Introduction
A functional world
5. Asynchronous Scala: Promising futures
● Example
type Context = (Input,Output,Error)
type Action = Context => (Context,Event)
def main(
actions: Iterable[Action], context: Context):(Context,Seq[Event]) = {
((context,Seq.empty[Event]) /: actions) {
case ((context,events),actions) =>
action.apply(context) match {
case (context,event) => (context, events :+ event)
}
}
}
Introduction
A functional world
6. Asynchronous Scala: Promising futures
● Problem? World actions are not precalculated.
What happens to I/O?
● World can be considered as
○ asynchronous: Things may happen at same time
○ reactive: Things may happen due to
■ actions: that trigger …
■ ...events: action consequences.
Introduction
A functional world
8. Asynchronous Scala: Promising futures
● Scala’s concurrency model is built on Java’s
● java.lang.Thread
val myThread = new Thread(new Runnable {
def run(){
println(“hi”)
}
}
myThread.start()
Introduction
Threads
9. Asynchronous Scala: Promising futures
● Thread improvements
○ ExecutorService (obtained from static Executors) allows using
thread policies (like threading pools)
val pool: ExecutorService = Executors.newFixedThreadPool(poolSize)
pool.execute(new Runnable{
def run(){
println(“I’m handling a request”)
}
})
○ Anyway, Threads abstraction level is too low
Introduction
Thread policies
11. Asynchronous Scala: Promising futures
● By default, non-blocking operations
● They will hold a T value at some point
● So a future may be uncompleted(it has no value yet) or completed
● Completion will be treated as a scala.util.Try value
It will have two possible values:
○ Success(t: T)
○ Failure(t: Throwable)
Futures
Overview
12. Asynchronous Scala: Promising futures
● Successfully completion example
import scala.concurrent._
import ExecutionContext.Implicits.global
val firstPrimeNumbers: Future[List[Int]] = Future {
List(1,2,3,5,7,11,13)
//what if 'calculateFirstPrimeNumbers(100000)'…
}
res0: Future[List[Int]]
Futures
Success on completion
13. Asynchronous Scala: Promising futures
● Failure completion example
import scala.concurrent._
import ExecutionContext.Implicits.global
val thisWillFail: Future[Int] = Future(2 / 0)
res0: Future[Int]
Futures
Failure on completion
14. Asynchronous Scala: Promising futures
● A future, once it’s completed, it never changes of value
● An ExecutionContext
○ executes tasks submitted to them.
○ They can be seen as thread pools.
○ Most of future ops require an implicit ExecutionContext.
Futures
ExecutionContext
15. Asynchronous Scala: Promising futures
● Expecting results.
○ Blocker way (discouraged but sometimes mandatory).
○ Non-blocker way: using callbacks
Futures
Expecting results
17. Asynchronous Scala: Promising futures
● Blocking: Await (Problem: Not enough time)
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
val f: Future[Int] = Future{
Thread.sleep(10000)
2
}
println(Await.result(f,5.seconds))
java.util.concurrent.TimeoutException: Futures timed out after [5 seconds]
Futures
Blocking: Await problem
18. Asynchronous Scala: Promising futures
● Non-Blocking: callbacks
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
val f: Future[Int] = Future{
Thread.sleep(10000)
2
}
f.onComplete( n => println(n) )
//at some point, “Success(2)” will appear
Futures
Non-blocking: Callbacks
Non-blocking
19. Asynchronous Scala: Promising futures
● Callbacks will be executed asynchronously when future is
completed
● Try[T] => U
● Try[T] ~ Either[Throwable,T]
○ Left(throwable) ~ Failure(throwable)
○ Right(t) ~ Success(t)
Futures
Callbacks
20. Asynchronous Scala: Promising futures
● onComplete
f.onComplete( (t: Try[Int]) => println(n) )
//Success(2)
● onSuccess
f.onSuccess( n => println(n) )
//2
● onFailure
f.onFailure( throwable => println(throwable.getMessage) )
//it will never print an error (because it equals Success(2))
Futures
Callbacks
21. Asynchronous Scala: Promising futures
● Composition
○ Future is a monad
■ Type Constructor: T => Future[T]
■ Unit Function: Future.apply
■ Bind Function: flatMap
○ Since Future has map,flatMap,filter methods; it can be composed
easily in a for-comprehension
Futures
Monad behavior
31. Asynchronous Scala: Promising futures
● Futures can be created by
○ Future.apply
○ Promises
● You can think about it like
○ Future ~ Read future value
○ Promise ~ Write future value
● Promises are single-assigned (just once. Immutable as futures)
Promises
Overview
32. Asynchronous Scala: Promising futures
Promises
Baggage & claim pattern
Menu
order
Menu
Being
Cooked
Ticket
Menu
Ready
33. Asynchronous Scala: Promising futures
Promises
Baggage & claim pattern
Promise[T]
Begin
completion
Future[T]
p.success
or
p.failure
Try[T]
34. Asynchronous Scala: Promising futures
Promises
Example
val producer = future {
val r: T = produceSomething()
p success r
continueDoingSomethingUnrelated()
}
val consumer = future {
startDoingSomething()
f onSuccess {
case r: T => handleResult()
}
}
val p = promise[T]
val f = p.future
35. Asynchronous Scala: Promising futures
● complete
val p: Promise[Int]
p.complete(Try(2))
● completeWith
val p: Promise[Int]
p.completeWith(Future(2))
Promises
Overview
37. Still interested?
● Scala school (Twitter)
● Reactive Design Patterns, Roland
Kuhn and Jamie Allen
● Scala-lang docs: Futures and
promises
● Akka doc - Futures