The recently released Scala 2.10.0 introduces futures and promises.
One of the most prominent highlights of this release, futures make it trivial to compose asynchronous multi-threaded apps.
And you can do so elegantly as I try to demonstrate with a few examples.
// example 1
//
// `future` blocks asynchronously execute in a different thread and return a `val`
// asynchronous results can be trapped via `onSuccess`, `onFailure` and `onComplete` callbacks
val sayHello = future {
Thread.sleep(1000)
"hello"
}
sayHello onSuccess {
case message => Console.println(s"He said '$message'")
}
Console.println("Waiting..")
Thread.sleep(2000)
// output
//
// Waiting..
// He said 'hello'
val tryDivideByZero = future {
Thread.sleep(1000)
1 / 0
}
tryDivideByZero onFailure {
case e: ArithmeticException => Console.println(s"Don't be silly!")
}
Console.println("Try dividing by zero")
Thread.sleep(2000)
// output
//
// Try dividing by zero
// Don't be silly!
// example 2
//
// if one future depends on the result of another
// you could nest callbacks
// or use `map` to "chain" them
// `map` returns a future which can be trapped via callbacks
val firstLove = future {
Thread.sleep(500)
"i love you"
}
val thenBetray = firstLove map {
case loveLetter => {
Console.println(loveLetter)
Thread.sleep(500)
"not really"
}
}
thenBetray onSuccess {
case partingWords => Console.println(partingWords)
}
Thread.sleep(2000)
// output
//
// i love you
// not really
// example 3
//
// multiple inter-dependent futures typically create a nested callback mess
// this is avoided with the `for` construct
// `for` can "chain" multiple futures, and "apply" another `future` on their results
val calculateMyScore = future {
Thread.sleep(500)
new Random().nextInt(10)
}
val calculateYourScore = future {
Thread.sleep(500)
new Random().nextInt(10)
}
val doIWin = for {
myScore <- calculateMyScore
yourScore <- calculateYourScore
} yield myScore > yourScore
doIWin onSuccess {
case b: Boolean => Console.println(if (b) "yes" else "no")
}
Console.println("Do I win?")
Thread.sleep(2000)
// output
//
// Do I win?
// yes|no
The entire example - available on GitHub - is an executable application.
The main app runs on its own thread and each future block uses a thread from the global execution context thread pool.
Timers Thread.sleep(...) are included to simulate asynchronous calls.