Dispatchers & Threading
KOTLIN › Coroutines
Which thread runs a coroutine: the built-in dispatchers, limitedParallelism, main-safety, and confinement.
Dispatchers are where coroutines meet real threads, so interviewers use them to check whether you understand the threading model underneath rather than the API on top. Expect to justify Main versus IO versus Default, explain why IO can exceed the core count when both share a pool, and say what withContext actually costs. Strong answers reach for limitedParallelism instead of custom pools, treat main-safety as a property of the function rather than a ritual at the call site, and inject dispatchers so the code stays testable.
What this covers
- A dispatcher decides which thread runs a coroutine, acting at resumption points; a suspended coroutine holds no thread
- Dispatchers.Main is a Handler on the main Looper; Main.immediate skips the post when already on the main thread
- IO and Default share one pool: Default is capped at core count, IO at 64, because blocked threads are not computing
- limitedParallelism(n) caps concurrency without creating threads, and limitedParallelism(1) gives lock-free confinement
- Dispatchers.Unconfined does not dispatch: it runs inline on the caller until the first suspension, then resumes anywhere
- withContext switches for its block and returns to the original context, which is what makes a suspend function main-safe
- withContext has real cost: hoist the switch out of loops, and do not wrap non-blocking functions in it
- asCoroutineDispatcher() wraps an Executor but you own the threads and must close it; prefer limitedParallelism
- Inject dispatchers as constructor parameters; Dispatchers.setMain covers the one viewModelScope hard-codes
Study this topic
- Dispatchers & Threading explained: the guided lesson
- 18 practice quiz questions
- 15 revision flashcards
- Dispatchers & Threading interview questions and answers