ExecutionContext

Contains factory methods for creating execution contexts.

Companion
class
Source
ExecutionContext.scala
class Object
trait Matchable
class Any

Type members

Classlikes

WARNING: Only ever execute logic which will quickly return control to the caller.

WARNING: Only ever execute logic which will quickly return control to the caller.

This ExecutionContext steals execution time from other threads by having its Runnables run on the Thread which calls execute and then yielding back control to the caller after *all* its Runnables have been executed. Nested invocations of execute will be trampolined to prevent uncontrolled stack space growth.

When using parasitic with abstractions such as Future it will in many cases be non-deterministic as to which Thread will be executing the logic, as it depends on when/if that Future is completed.

Do *not* call any blocking code in the Runnables submitted to this ExecutionContext as it will prevent progress by other enqueued Runnables and the calling Thread.

Symptoms of misuse of this ExecutionContext include, but are not limited to, deadlocks and severe performance problems.

Any NonFatal or InterruptedExceptions will be reported to the defaultReporter.

Source
ExecutionContext.scala

Value members

Concrete methods

Creates an ExecutionContext from the given Executor.

Creates an ExecutionContext from the given Executor.

Value Params
e

the Executor to use. If null, a new Executor is created with default configuration.

reporter

a function for error reporting

Returns

the ExecutionContext using the given Executor

Source
ExecutionContext.scala

Creates an ExecutionContext from the given Executor with the default reporter.

Creates an ExecutionContext from the given Executor with the default reporter.

Value Params
e

the Executor to use. If null, a new Executor is created with default configuration.

Returns

the ExecutionContext using the given Executor

Source
ExecutionContext.scala

Creates an ExecutionContext from the given ExecutorService.

Creates an ExecutionContext from the given ExecutorService.

Value Params
e

the ExecutorService to use. If null, a new ExecutorService is created with default configuration.

reporter

a function for error reporting

Returns

the ExecutionContext using the given ExecutorService

Source
ExecutionContext.scala

Creates an ExecutionContext from the given ExecutorService with the default reporter.

Creates an ExecutionContext from the given ExecutorService with the default reporter.

If it is guaranteed that none of the executed tasks are blocking, a single-threaded ExecutorService can be used to create an ExecutionContext as follows:

import java.util.concurrent.Executors
val ec = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
Value Params
e

the ExecutorService to use. If null, a new ExecutorService is created with default configuration.

Returns

the ExecutionContext using the given ExecutorService

Source
ExecutionContext.scala

Concrete fields

The default reporter simply prints the stack trace of the Throwable to System.err.

The default reporter simply prints the stack trace of the Throwable to System.err.

Returns

the function for error reporting

Source
ExecutionContext.scala

The global ExecutionContext.

The global ExecutionContext. This default ExecutionContext implementation is backed by a work-stealing thread pool. It can be configured via the following system properties:

  • scala.concurrent.context.minThreads = defaults to "1"

  • scala.concurrent.context.numThreads = defaults to "x1" (i.e. the current number of available processors * 1)

  • scala.concurrent.context.maxThreads = defaults to "x1" (i.e. the current number of available processors * 1)

  • scala.concurrent.context.maxExtraThreads = defaults to "256"

The pool size of threads is then numThreads bounded by minThreads on the lower end and maxThreads on the high end.

The maxExtraThreads is the maximum number of extra threads to have at any given time to evade deadlock, see scala.concurrent.blocking.

The global execution context can be used explicitly, by defining an implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global, or by importing ExecutionContext.Implicits.global.

Batching short-lived nested tasks

Asynchronous code with short-lived nested tasks is executed more efficiently when using ExecutionContext.opportunistic (continue reading to learn why it is private[scala] and how to access it).

ExecutionContext.opportunistic uses the same thread pool as ExecutionContext.global. It attempts to batch nested task and execute them on the same thread as the enclosing task. This is ideally suited to execute short-lived tasks as it reduces the overhead of context switching.

WARNING: long-running and/or blocking tasks should be demarcated within scala.concurrent.blocking-blocks to ensure that any pending tasks in the current batch can be executed by another thread on global.

How to use

This field is private[scala] to maintain binary compatibility. It was added in 2.13.4, code that references it directly fails to run with a 2.13.0-3 Scala library.

Libraries should not reference this field directly because users of the library might be using an earlier Scala version. In order to use the batching ExecutionContext in a library, the code needs to fall back to global in case the opportunistic field is missing (example below). The resulting ExecutionContext has batching behavior in all Scala 2.13 versions (global is batching in 2.13.0-3).

implicit val ec: scala.concurrent.ExecutionContext = try {
 scala.concurrent.ExecutionContext.getClass
   .getDeclaredMethod("opportunistic")
   .invoke(scala.concurrent.ExecutionContext)
   .asInstanceOf[scala.concurrent.ExecutionContext]
} catch {
 case _: NoSuchMethodException =>
   scala.concurrent.ExecutionContext.global
}

Application authors can safely use the field because the Scala version at run time is the same as at compile time. Options to bypass the access restriction include:

  1. Using a structural type (example below). This uses reflection at run time.

  2. Writing a Scala object in the scala package (example below).

  3. Writing a Java source file. This works because private[scala] is emitted as public in Java bytecode.

// Option 1
implicit val ec: scala.concurrent.ExecutionContext =
 (scala.concurrent.ExecutionContext:
   {def opportunistic: scala.concurrent.ExecutionContextExecutor}
 ).opportunistic

// Option 2
package scala {
 object OpportunisticEC {
   implicit val ec: scala.concurrent.ExecutionContext =
     scala.concurrent.ExecutionContext.opportunistic
 }
}
Returns

the global ExecutionContext

Source
ExecutionContext.scala