Futures let us run values off the main thread and handle background or yet to be run values by mapping them with callbacks. See how they work in Scala.
Futures allow us to run values off the main thread and handle values that are running in the background or yet to be executed by mapping them with callbacks.
If you come from a Java background, you might be aware of java.util.concurrent.Future. There are several challenges in using this:
Threads are always blocked while retrieving values.
The wait time for the completion of computation.
The GET method is the only way to retrieve values.
It’s a weary andantagonistic way of writing concurrent code.
We have better Futures in Scala with Scala.concurrent.Future. With Scala Futures, we can achieve:
Real-time non-blocking computations.
Callbacks for onComplete (success/failure), i.e., values in Future are instances of the Try clause.
The mapping of multiple Futures.
Futures are immutable by nature and are cached internally. Once a value or exception is assigned, Futures cannot be modified/overwritten (it’s hard to achieve referential transparency).
println("where is your boss? you only got 1 second ,you are about to be killed by Scala compiler")
8
Thread.sleep(1000)
9
println("Finding Francis...")
10
} // Add your logic
11
12
valwhereIsFrancis=Future {
13
findingFrancis
14
// wait time until the login executes, returns nothing if the code is compiled soon by compiler that then future is executed
15
}
16
}
ExecutionContext
Think of ExecutionContext as an administrator who allocates new threads or uses a pooled/current thread (not recommended) to execute Futures and their functions. Without importing ExecutionContext into scope, we cannot execute a future.
Global ExecutionContext is used in many situations to dodge the need to create a custom ExecutionContext. The default global ExecutionContext will set the parallelism level to the number of available processors (can be increased).
Callbacks
Futures eventually return values that needs to be handled by callbacks. Unhandled values/exceptions will be lost.
Futures have methods that you can use. Common callback methods are:
onComplete callback values in Future are instances of the Try clause:
Scala
xxxxxxxxxx
1
1
defonComplete[U](f: Try[T] =>U)(implicitexecutor: ExecutionContext): Unit
onSuccess and onFailure are deprecated. You can use filter, foreach, map, and many more — learn more here.
Scala
xxxxxxxxxx
1
1
whereIsFrancis.onComplete {
2
caseSuccess(foundFrancis) =>println(s"heads up dummy $foundFrancis")
This requires Duration import for seconds. To handle time in concurrent applications, Scala has:
Scala
xxxxxxxxxx
1
1
importscala.concurrent.duration._
This support different time units: toNanos, toMicros, toMillis, toSeconds, toMinutes, toHours, toDays, and toUnit(unit: TimeUnit).
For bulky code, callbacks are not always the best approach. Scala futures can be used with for (enumerators) yield e, where enumerators refers to a semicolon-separated list. An enumerator is either a generator which introduces new variables or it is a filter.
When asynchronous computations throw unhandled exceptions, Futures associated with those computations fail. Failed futures store an instance of Throwable instead of the result value. Future provides the failed projection method, which allows the Throwable to be treated as the success value of another Future.
Projections
To allow us to understand a result returned as an exception, Futures also have projections. If the original Future fails, the failed projection returns a future containing a value of type Throwable. If the original Future succeeds, the failed projection fails with a NoSuchElementException.
After making the main thread wait two seconds, we get to see the output from the Future thread as below:
Conclusion
Futures are a great approach to run parallel programs in an efficient and non-blocking way. We can achieve this in a more functional way using external libraries (scalaz, cats, etc.).
Akka is an actor model library built on Scala and provides a way to implement long-running parallel processes (to overcome limitations of Scala Futures). Futures are used in other frameworks that are built using Scala like Play Framework, lagom, Apache Spark, etc.
Check out our page YolkOrbit for more on Scala and Akka.
Comments