Future Sequence in Scala

  1. Run Futures Sequentially in Scala
  2. Concurrent/Parallel Execution of Futures in Scala
  3. Conclusion

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.

Note: Run the codes below in local IDE, not online compilers, to see them run properly and see the difference between them.

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.

Run Futures Sequentially in Scala

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:

Concurrent Execution of Futures in Scala

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.

Write for us
DelftStack articles are written by software geeks like you. If you also would like to contribute to DelftStack by writing paid articles, you can check the write for us page.