Learn

Learn about latest technology

Build

Unleash your talent and coding!

Share

Let more people use it to improve!
 

With Futures in Scala who brings the core, Java Concurrency api?

lunes, 6 de abril de 2020

In this post I won't talk about Scala  Future's Syntax, you can find everything at Scala Official documentation or in thousands of blogs. So at this point is very clear and obvious what the Scala Future for in Scala concurrent programming and how to use it, so perhaps the best solution for concurrency and any other asynchronous processing in Scala are the FUTURES. It's mean that our processes will be execute asynchronously and doing this we'll have a lot of benefits for instance executing different computations at the same time.

My challenge today will be just try to explain what is the core of futures and who provide its. In few words I gonna try to give you an idea about the relationship between Scala Concurrency package and Java Concurrency package. How like in too many other Scala modules in concurrency Scala construct its core over java concurrency pillars.

I guess you know the following concepts, but I just want to mention some of them:

  • A Runnable is basically a type of class (Runnable is an Interface) that can be put into a thread as is explained in the java spec [Should be implemented by any class whose instances are intended to be executed by a thread].


  • A Thread is a thread of execution in a program, lightweight processes.



It is important to notice that in every small applications there's a close connection between the task being done by a new thread, as defined by its Runnable object, and the thread itself, as defined by a Thread object. But in large applications make sense to separate thread management and creation from the rest of the application so in these cases. The Object object that encapsulates this tasks(creation of threads, execution of tasks in these threads etc.) are known as Executors.


The strategy used in Scala to deal with the Futures will be the Executor, who is responsible for executing computations. This Executor come from the java concurrency api. So Futures in Scala revolve around ExecutionContexts,  but this is nearly a copy  of our java Executor, our Scala ExecutionContext implement the Executor java interfaces. So all our computations are executed in a wrapper of our aforementioned java Executor.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
.........

/**
 * An [[ExecutionContext]] that is also a
 * Java [[http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html Executor]].
 */
trait ExecutionContextExecutor extends ExecutionContext with Executor

/**
 * An [[ExecutionContext]] that is also a
 * Java [[http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html ExecutorService]].
 */
trait ExecutionContextExecutorService extends ExecutionContextExecutor with ExecutorService

.........

The snapshot source code above is ExecutionContext.scala. Basically the main job here is done by java concurrency api, once again. Execution context execute Runnable(the task to execute).

In java concurrency api most of the executor implementations use thread pools, which consist of worker threads. This kind of thread exists separately from the Runnable and Callable tasks it executes and is often used to execute multiple tasks.

Using worker threads minimizes the overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and deallocating many thread objects creates a significant memory management overhead.


One common type of thread pool is the fixed thread pool. This type of pool always has a specified number of threads running; if a thread is somehow terminated while it is still in use, it is automatically replaced with a new thread. Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever there are more active tasks than threads.

One of the Cores in our ExecutionContext that is behind the scenes is the java Fork/Join framework.
Fork/join let us take advance of multiple processors when we work in this kind of environment.
Its work is done distributing tasks to worker threads(explained above) in a thread pool. The core in this Framework is  the ForkJoinPool class.

The ForkJoinPool's goal is to use all the available processing power to enhance the performance of your application and there are some aspect that you can get as default values or you can set for a custom performance like available processors.

We can create our own ExecutionContext but the language recommendation is that we should use the ExecutionContext.global that comes from scala.concurrent package. This Global Execution Context  is backed by the ForkJoinPool aforementioned. Once again the main job is done by java concurrency api.

By default the ExecutionContext.global sets the parallelism level of its underlying fork-join pool to the number of available processors but you can set this properties and others like :

  • scala.concurrent.context.minThreads - defaults to Runtime.availableProcessors
  • scala.concurrent.context.numThreads - can be a number or a multiplier (N) in the form ‘xN’ ; defaults to Runtime.availableProcessors
  • scala.concurrent.context.maxThreads - defaults to Runtime.availableProcessors


I just want to give you an idea about the Scala Future behind the scene that in my opinion everything is a wrapper of java.concurrency api.


Definitely if you need to do an intensive use of Future and multitasking in Scala, increasing your performance in concurrent customized operations you will need to have a look to Java Concurrency Api.