Coroutine Dispatchers: Telling Your Coroutines Which Thread to Use

A Dispatcher tells a coroutine which thread or thread pool to use for its work. Use Dispatchers.Default for CPU-intensive tasks. If none is specified, it inherits from its parent. The main footgun: Unconfined can resume on an unexpected thread.
Why it exists
Modern applications need to perform long-running tasks like complex calculations without freezing the main thread. Coroutines need a mechanism to switch between threads easily to handle this. Dispatchers are that mechanism, providing a structured way to assign work to an appropriate thread.
The mental model
A Dispatcher is like a work scheduler for your coroutines. It looks at the work a coroutine needs to do and assigns it to the right thread or pool of threads. Just as you wouldn't ask your UI designer to do heavy data processing, you use dispatchers to send CPU-intensive work to background threads, keeping the main thread free and responsive.
How it works
Every coroutine runs in a CoroutineContext, and the CoroutineDispatcher is a key part of it. When you launch a coroutine, you can explicitly provide a dispatcher. If you don't, it inherits the dispatcher from its parent CoroutineScope. Common choices include Dispatchers.Default, which uses a shared background pool of threads, or creating a new thread with newSingleThreadContext.
When to use it
You should explicitly specify a dispatcher when you need to ensure a task runs on a particular type of thread. Use Dispatchers.Default for sorting a large list, processing data, or any CPU-bound operation that shouldn't block the calling thread. If a coroutine's work must be confined to a single, dedicated thread, newSingleThreadContext is an option, but it's a resource-intensive one.
When not to use it
Avoid Dispatchers.Unconfined in general code. It starts the coroutine on the current thread but resumes on whatever thread the suspending function used, making its behavior unpredictable. This can lead to subtle bugs or crashes, especially if it attempts to modify state confined to a specific thread. Also, avoid creating threads with newSingleThreadContext unless you have a clear strategy for managing the created thread's lifecycle, as it's an expensive resource that must be closed or reused.
One canonical example
A coroutine launched with Dispatchers.Unconfined on the main thread will start on main. But after a suspending call like delay(), it might resume on a background thread from the default executor pool. In contrast, a coroutine launched in the same scope without a specific dispatcher will inherit the main thread context and resume on the main thread after its delay, ensuring predictable execution.
Interview question
Which statement best describes why Dispatchers.Unconfined is generally discouraged for common use cases?
- a.It prevents coroutines from ever inheriting a dispatcher from their parent scope.
- b.It always forces coroutines to run on the main thread, causing UI freezes.
- c.It allocates a new thread for every coroutine, leading to high overhead.
- d.Its behavior after a suspending function can lead to unpredictable thread execution.Correct
Why? this is the answer
Dispatchers.Unconfined is discouraged because it starts on the current thread but can resume on any thread used by a suspending function, leading to unpredictable execution. This is distinct from creating new threads (which is more relevant to newSingleThreadContext) or always running on the main thread.
Just read this? Test yourself on what you have been reading.
Read the original → kotlinlang.org
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on kotlin — each one lists the topics its interview covers.
See open roles