2024.1+Coroutine Dispatchers
Edit pageLast modified: 26 February 2025tip
Kotlin Coroutines×IntelliJ PlatformThis section focuses on explaining coroutines in the specific context of the IntelliJ Platform. If you are not experienced with Kotlin Coroutines, it is highly recommended to get familiar with Learning Resources first.
Coroutines are always executed in a context represented by CoroutineContext
. One of the most important parts of the context is a dispatcher, which determines what thread or thread pool the corresponding coroutine is executed on.
In the IntelliJ Platform, coroutines are executed on three main dispatchers:
Default Dispatcher
The Dispatchers.Default
dispatcher is used for performing CPU-bound tasks.
It ensures that the number of tasks running in parallel does not exceed the number of CPU cores. A hundred threads performing CPU-bound work on a machine with 10 CPU cores can result in threads competing for CPU time and excessive thread switching. This makes the IDE effectively slower, hence the limitation. Using the default dispatcher (or its limitedParallelism()
slice) enables a consistent CPU load.
IO Dispatcher
The Dispatchers.IO
dispatcher is used for performing IO operations like reading/writing to files, network, executing external processes, etc.
It must be used at the very deep moment in the trace right before the actual IO operation happens and exited as soon as the operation is finished. Example:
Wrong
suspend fun readDataFromFile(): Data { return withContext(Dispatchers.IO) { val fileName = computeFileName() val bytes = readFile(fileName) Data(parseBytes(bytes)) }}
Correct
suspend fun readDataFromFile(): Data { val fileName = computeFileName() val bytes = withContext(Dispatchers.IO) { readFile(fileName) } return Data(parseBytes(bytes))}
EDT Dispatcher
The Dispatchers.EDT
dispatcher is used for executing UI actions on the Swing Event Dispatch Thread. Dispatchers.EDT
dispatches onto EDT within the context modality state.
Dispatchers.Main
vs. Dispatchers.EDT
In Kotlin, a standard dispatcher for UI-based activities is Dispatchers.Main
.
In the IntelliJ Platform, Dispatchers.Main
differs from Dispatchers.EDT
:
It is forbidden to initiate read or write actions in
Dispatchers.Main
.Dispatchers.Main
is a pure UI dispatcher, and accidental access to the IntelliJ Platform model could cause UI freezes.Dispatchers.Main
usesany
modality state if it cannot infer modality from the coroutine context. This helps to ensure progress guarantees in libraries that useDispatchers.Main
.
In the IntelliJ Platform, the EDT dispatcher is also installed as Dispatchers.Main
so both can be used, however always prefer Dispatchers.EDT
.
Use Dispatchers.Main
only if the coroutine is IntelliJ Platform-context agnostic (e.g., when it can be executed outside the IntelliJ Platform context). Use Dispatchers.EDT
when in doubt.
Dispatchers vs. Threads
The dispatcher concept is a higher level of abstraction over threads. While the code is always executed on threads, do not think about dispatchers as specific thread instances.
A single coroutine is not bound to the same thread during the whole execution time. It may happen that a coroutine starts on thread A, is suspended, and finished on thread B, even if the whole is executed with the same dispatcher context.
Consider the following code snippet:
suspend fun doSomething() {
val fetchedData = suspendingTask()
withContext(Dispatchers.EDT) {
updateUI(fetchedData)
}
}
suspend fun suspendingTask(): Data {
// fetch data from the internet
}
The following diagram presents one of the potential execution scenarios:
The code is executed as follows:
suspendingTask
is started and partially executed on Thread 2.suspendingTask
is suspended when it waits for data fetched from the internet.After receiving data,
suspendingTask
is resumed, but now it is executed on Thread 1.Execution explicitly switches to the EDT dispatcher and
updateUI
is executed on EDT.
warning
This behavior can result in unexpected consequences for code that relies on thread-specific data and assumes it will execute consistently on the same thread.
note
Something missing?If a topic you are interested in is not covered in the above sections, let us know via the Was this page helpful? feedback form below or other channels.
Please be specific about the topics and reasons for adding them, and leave your email in case we need more details. Thanks for your feedback!
Thanks for your feedback!