Scala supports parallelism and concurrency through various libraries and constructs, making it easier for the developer to write non-blocking, concurrent, and parallel code. One of the most popular constructs for concurrency in Scala is the ‘Future‘ and ‘Promise‘ mechanism, which is part of the standard library.
## Futures
In Scala, a ‘Future‘ represents a value that will be available at some point in the future. It is a construct that allows us to express computations that will happen concurrently, without explicitly dealing with threads.
Futures in Scala are created using the ‘Future.apply‘ method, which takes a single parameter - the computation to be executed concurrently. The method also takes an implicit execution context, which is usually provided by importing ‘scala.concurrent.ExecutionContext.global‘.
Here’s an example of creating a future to compute the square of an integer:
import scala.concurrent._
import scala.concurrent.ExecutionContext.global
val squareFuture: Future[Int] = Future {
val num = 4
num * num
}
To get the result of the computation when it completes, you can use the ‘onComplete()‘ method, which takes a callback function. This function is called when the future is either completed successfully or failed with an exception. Here’s an example:
import scala.util._
squareFuture.onComplete {
case Success(value) => println(s"Result: $value")
case Failure(exception) => println(s"Error: ${exception.getMessage}")
}
Note that the ‘onComplete()‘ method and its callback are non-blocking.
## Promises
A ‘Promise‘ is a mutable object that can be completed with a value or an exception. Promises provide a way to create a ‘Future‘ and control its completion. Once a ‘Promise‘ is completed, any ‘Future‘ associated with it will be completed with the same result.
Here’s an example of creating and completing a promise:
import scala.concurrent._
import scala.concurrent.ExecutionContext.global
import scala.util._
val promise: Promise[Int] = Promise[Int]()
val future: Future[Int] = promise.future
future.onComplete {
case Success(value) => println(s"Result: $value")
case Failure(exception) => println(s"Error: ${exception.getMessage}")
}
val num = 4
val square = num * num
promise.success(square) // Complete the promise with the square value
Promises are useful when working with external libraries that expect you to provide a callback function to handle asynchronous results. Using a promise, you can create a future that will be completed when the callback is called.
Keep in mind that ‘Promise‘ is a one-shot construct. You can only complete it once. If you try to complete it more than once, you will get an exception.
## Conclusion
Scala provides support for parallelism and concurrency through the use of ‘Future‘ and ‘Promise‘ constructs, which allow developers to write non-blocking and concurrent code. ‘Future‘ represents a computation that will be completed in the future (possibly concurrently), while ‘Promise‘ provides a way to complete a ‘Future‘ with a value or an exception.
Together, these constructs provide a powerful and easy-to-use toolkit for writing concurrent and parallel applications in Scala.