In Kotlin Coroutines, Dispatchers determine the thread or thread pool on which a coroutine will run. Choosing the right dispatcher ensures optimal performance and responsiveness.

๐Ÿšฆ Built-in Dispatchers

๐Ÿ”น Dispatchers.Main

Purpose: For UI-bound tasks.

Thread Context: Runs on the main/UI thread.

Available On: Android, JavaFX, Swing (requires a kotlinx-coroutines-android or kotlinx-coroutines-javafx dependency).

Use Cases:

  • Updating UI after loading data
  • Responding to user events (e.g. clicks)

โš ๏ธ Do not perform blocking or heavy computations here.

๐Ÿ”น Dispatchers.IO

Purpose: Designed for blocking I/O operations.

Thread Context: A shared pool of threads.

Scalability: Dynamically grows up to ~64 threads by default (more than CPU cores).

Use Cases:

  • Reading/writing files
  • Network or database calls (JDBC, Retrofit)

โœ… Blocking allowed โ€” suitable for legacy APIs.

๐Ÿ”น Dispatchers.Default

Purpose: For CPU-intensive operations.

Thread Context: Uses a thread pool with number of threads = number of CPU cores.

Use Cases:

  • Complex algorithms
  • Data crunching, sorting, parsing

๐Ÿšซ Avoid blocking I/O here โ€” designed for non-blocking compute tasks.

๐Ÿ”น Dispatchers.Unconfined (less common)

Purpose: Starts coroutine in the current thread but resumes in the thread of the suspending function.

Thread Context: No fixed thread.

Use Cases:

  • For debugging or advanced coroutine control
  • Lightweight coroutines not bound to any thread

โš ๏ธ Can lead to unexpected behavior; not recommended for UI or production use.

๐Ÿ› ๏ธ Creating a Custom Dispatcher

val myDispatcher = Executors.newFixedThreadPool(4).asCoroutineDispatcher()

Use when:

  • You want fine-grained control over threading (e.g. limiting concurrency)
  • Need a dedicated thread pool for certain tasks

โš ๏ธ Donโ€™t forget to close it after use:

myDispatcher.close()

โœ… Choosing the Right Dispatcher โ€“ Summary Table

DispatcherIdeal ForBacked ByBlocking Allowed?Scalability
Dispatchers.MainUI updates, UI event handlingMain/UI threadโŒ NoโŒ Low
Dispatchers.IOFile, network, DB I/OLarge shared thread poolโœ… Yesโœ… High
Dispatchers.DefaultCalculations, CPU tasksCPU core thread poolโŒ Noโž– Medium
Dispatchers.UnconfinedExperimental, coroutine chainingCallerโ€™s thread (initially)โš ๏ธ Dependsโž– Low

๐Ÿ’ก Best Practices

  • Use Main only for UI work
  • Use IO for anything blocking
  • Use Default for heavy logic
  • Avoid Unconfined unless you know what youโ€™re doing
  • Combine with withContext(dispatcher) to offload work

To learn more about Android development and concurrency: