Future Sequence in Scala
In this article, we will learn about futures
in Scala.
In Scala, Future
is a value that may not be available currently but will be in the future.
When we want to run tasks concurrently/parallelly in Scala, we use Futures
. Although we could use a native Java thread
, Scala Future
is preferred as it is much simpler to write.
Simply put, Future
provides simple ways to run an algorithm/application concurrently. When a future is created, it starts running concurrently and gives results at some point that is eventually at, some point we get the results.
Run Futures
Sequentially in Scala
When futures
starts executing sequentially, it is a sequential run. We have to import ExecutionContext
, which manages the thread pool; without it, the future
will not run.
Let’s look at an example to understand it better.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Example extends App {
def task(n: Int) = Future
{
Thread.sleep(1000)
println(n) //to observe the output
n + 1
}
//running in a sequential way
val temp = for {
t1 <- task(1)
t2 <- task(t1)
t3 <- task(t2)
t4 <- task(t3)
t5 <- task(t4)
} yield List(t1,t2,t3,t4,t5)
temp.map(x => println(s"Completed. ${x.size} tasks were executed"))
Thread.sleep(5000) //so that the main thread doesn't quit quickly
}
When the code is run, we see that our 5 tasks are executed in sequential order, one after the other.
Concurrent/Parallel Execution of Futures in Scala
Example code:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object Example extends App {
def task(n: Int) = Future
{
Thread.sleep(1000)
println(n) //to observe the output
n + 1
}
val temp = for {
t1 <- task(1)
t2 <- Future.sequence(List(task(t1), task(t1)))
t3 <- task(t2.head)
t4 <- Future.sequence(List(task(t3), task(t3)))
t5 <- task(t4.head)
} yield t2.size + t4.size
temp.foreach(x => println(s"Done. $x task run in concurrent manner"))
Thread.sleep(6000) // needed to prevent the main thread from quitting
// too early
}
In the code above, we have used the Future.sequence
, which takes the list of futures
and converts them into a future of list
. All the tasks/jobs we want to run concurrently must be passed as a list.
Output:
When the code above is executed, we see that t2
and t4
are executed parallelly. One thing to remember while working with parallelism is that execution may not always be parallel as it depends on the availability of the threads.
If only a few threads are present, then only a few jobs will run in parallel while others wait for the threads to be freed.
Conclusion
In this tutorial, we understood what Futures
are and how they are useful in concurrently writing and running programs.