Contains factory methods for creating execution contexts.
- Companion
- class
- Source
- ExecutionContext.scala
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
Runnable
s run on the Thread
which calls execute
and then yielding back control
to the caller after *all* its Runnable
s 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 Runnable
s submitted to this ExecutionContext
as it will prevent progress by other enqueued Runnable
s and the calling Thread
.
Symptoms of misuse of this ExecutionContext
include, but are not limited to, deadlocks
and severe performance problems.
Any NonFatal
or InterruptedException
s 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. Ifnull
, a newExecutor
is created with default configuration.- reporter
a function for error reporting
- Returns
the
ExecutionContext
using the givenExecutor
- 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. Ifnull
, a newExecutor
is created with default configuration.
- Returns
the
ExecutionContext
using the givenExecutor
- Source
- ExecutionContext.scala
Creates an ExecutionContext
from the given ExecutorService
.
Creates an ExecutionContext
from the given ExecutorService
.
- Value Params
- e
the
ExecutorService
to use. Ifnull
, a newExecutorService
is created with default configuration.- reporter
a function for error reporting
- Returns
the
ExecutionContext
using the givenExecutorService
- 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. Ifnull
, a newExecutorService
is created with default configuration.
- Returns
the
ExecutionContext
using the givenExecutorService
- 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:
Using a structural type (example below). This uses reflection at run time.
Writing a Scala
object
in thescala
package (example below).Writing a Java source file. This works because
private[scala]
is emitted aspublic
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