Dispatchers — mga pangunahing konsepto, mga uri ng dispatcher at kung paano gumagana ang mga ito

May-akda: IT Sectr Nai-publish: 2026-06-22 Oras ng pagbabasa: 9 min

Dispatchers sa Kotlin Coroutines — mga bahagi ng CoroutineContext na tumutukoy sa mga thread para sa pagpapatupad ng mga coroutine: Main (UI-thread), IO (network at disk), Default (mga gawaing CPU-intensive) at Unconfined (kasalukuyang thread). Ang bawat dispatcher ay namamahala ng espesyalisadong pool ng thread, na na-optimize para sa partikular na uri ng trabaho. Ayon sa gabay ng JetBrains, 2024, ang pagpili ng tamang dispatcher ay kritikal para sa pagganap at katatagan ng aplikasyon.

Mga Pangunahing Punto

  • Dispatchers — mga paunang natukoy na dispatcher ng coroutine, namamahala sa pamamahagi ng mga gawain sa mga thread
  • Dispatchers.Main — Android UI-thread, para sa pag-update ng interface at pagtatrabaho sa View
  • Dispatchers.IO — pool para sa mga kahilingan sa network, pagbasa/pagsulat ng mga file at database (hanggang 64 na thread)
  • Dispatchers.Default — pool para sa mga gawaing CPU-intensive ayon sa bilang ng mga core ng processor
  • Dispatchers.Unconfined — pagmamana ng kasalukuyang thread, nang walang paglipat

Ano ang Dispatchers?

Dispatchers — mga implementasyon ng interface ng CoroutineDispatcher, na mga elemento ng CoroutineContext. Tinutukoy nila kung saang thread o pool ng thread isasagawa ang coroutine. Kapag lumilikha ng coroutine sa pamamagitan ng launch o async, ang dispatcher ay maaaring ipasa bilang unang parameter: launch(Dispatchers.IO) { ... }. Kung hindi tinukoy ang dispatcher, ito ay minamana mula sa panlabas na CoroutineScope.

Nagbibigay ang Kotlin ng apat na built-in na dispatcher: Main, IO, Default, Unconfined. Ang bawat dispatcher ay gumagamit ng sarili nitong pool ng thread, na na-optimize para sa partikular na uri ng operasyon. Ang tamang pagpili ng dispatcher ay tumutukoy sa pagganap ng aplikasyon: ang maling pagpili ay humahantong sa lag ng interface, idle CPU cores, o hindi mahusay na paggamit ng thread.

DispatcherPool ng threadMax. threadPaggamit
Dispatchers.MainIsa (UI)1Pag-update ng UI, LiveData, View
Dispatchers.IOIO pool64 (limitedParallelism)Network, mga file, database
Dispatchers.DefaultCPU poolN corePag-uuri, parsing, pag-compute
Dispatchers.UnconfinedKasalukuyang threadWALAMga operasyong pansamantala, pagsubok

Dispatchers.Main: UI-thread

Dispatchers.Main — dispatcher na nagpapatupad ng mga coroutine sa pangunahing thread ng Android. Ito ay inilaan para sa mga operasyong nauugnay sa interface: pag-update ng TextView, pagtawag ng notifyDataSetChanged, pagtatrabaho sa LiveData at StateFlow. Sa Android, ang dispatcher na ito ay ipinatupad sa pamamagitan ng Handler (Looper.getMainLooper()).

kotlin
// Tamang paglipat sa Main para sa mga update ng UI
viewModelScope.launch(Dispatchers.IO) {
    val data = repository.fetchData()
    withContext(Dispatchers.Main) {
        _uiState.value = data
    }
}

Kung ang coroutine ay nasa Main-dispatcher na, ang karagdagang withContext(Dispatchers.Main) ay hindi lumilikha ng overhead — sinusuri ng dispatcher ang kasalukuyang thread at nilalaktawan ang paglipat. withContext ang gustong paraan ng paglipat sa pagitan ng mga dispatcher.

Dispatchers.IO: network at mga operasyon sa disk

Dispatchers.IO — dispatcher na na-optimize para sa input-output operations: mga kahilingang HTTP (Ktor, OkHttp), pagbasa at pagsulat ng mga file, pagtatrabaho sa Room o SQLDelight. Ito ay gumagamit ng pool ng 64 na thread bilang default, nasusukat sa ilalim ng load. Ang bawat bagong kahilingang IO ay maaaring lumikha ng karagdagang thread hanggang maabot ang limitasyon.

Paglilimita ng paralelismo

Upang kontrolin ang bilang ng sabay-sabay na IO operations, gamitin ang limitedParallelism(). Ang function na ito ay lumilikha ng bagong dispatcher na may limitasyon sa bilang ng parallel thread, na pumipigil sa pagkaubos ng pool sa mga malawakang operasyon.

kotlin
val limitedIo = Dispatchers.IO.limitedParallelism(4)

// Mag-load ng 100 file na may limit na 4 na sabay-sabay na operasyon
coroutineScope {
    val files = (1..100).map { index ->
        async(limitedIo) {
            downloadFile("file_$index")
        }
    }
    files.awaitAll()
}

Gamitin ang IO-dispatcher para sa lahat ng operasyon kung saan ang coroutine ay gumugugol ng oras sa paghihintay (I/O-bound). Ang mga gawaing CPU-intensive sa IO-dispatcher ay hindi epektibo — sinasakop nila ang mga thread na para sa input-output, binabawasan ang throughput ng sistema.

Dispatchers.Default: mga gawaing CPU-intensive

Dispatchers.Default — dispatcher para sa mga operasyong pangkalkulasyon na nagbibigay-diin sa processor: pag-uuri, pag-filter, parsing ng JSON (Moshi, Kotlinx Serialization), pagproseso ng imahe, pag-compute. Ang laki ng pool ay katumbas ng bilang ng mga core ng processor (ngunit hindi bababa sa 2). Tinitiyak nito ang maximum na pag-load ng CPU nang walang paglipat ng konteksto.

kotlin
suspend fun processData(input: List<RawRecord>): List<ProcessedRecord> {
    return withContext(Dispatchers.Default) {
        input
            .parallelStream()
            .map { transform(it) }
            .toList()
    }
}

Huwag gamitin ang Dispatchers.Default para sa IO operations — haharangin nito ang mga thread ng CPU pool na maaaring magproseso ng mga gawaing pangkalkulasyon. Ang paghihiwalay sa IO at Default ay nagbibigay-daan sa optimal na paggamit ng mga mapagkukunan ng sistema: ang IO thread ay naghihintay ng input-output, ang CPU thread ay palaging abala sa pag-compute.

Dispatchers.Unconfined: kasalukuyang thread

Dispatchers.Unconfined — isang espesyal na dispatcher na hindi nagtatali ng coroutine sa anumang pool. Sinisimulan ng coroutine ang pagpapatupad sa parehong thread kung saan tinawag ang launch/async, at pagkatapos ng pagsususpinde ay magpapatuloy sa thread na tumawag sa resume. Ang ganitong pag-uugali ay angkop para sa mga pansamantalang operasyon na hindi nangangailangan ng nakapirming konteksto.

kotlin
fun main() = runBlocking {
    launch(Dispatchers.Unconfined) {
        println("Bago ang pagkaantala: ${Thread.currentThread().getName()}")
        delay(500L)
        println("Pagkatapos ng pagkaantala: ${Thread.currentThread().getName()}")
    }
}

Sa production code, ang Dispatchers.Unconfined ay bihirang ginagamit. Mga pangunahing kaso: magaan na pagbabago bago ipadala ang data sa ibang dispatcher at pagsubok. Para sa production load, gumamit ng tahasang dispatcher — ang Unconfined ay hindi mahuhulaan dahil ang thread ng pagpapatupad ay nakadepende sa implementasyon ng resume.

Paano pumili ng dispatcher

Ang pagpili ng dispatcher ay tinutukoy ng uri ng gawain: UI operations → Main, I/O-bound → IO, CPU-bound → Default, pansamantala → pagmamana mula sa scope. Para sa Android, inirerekomenda na simulan ang coroutine sa dispatcher kung saan ginagawa ang pangunahing trabaho, at bago ang pag-update ng UI, lumipat sa Main sa pamamagitan ng withContext.

  • Huwag patakbuhin ang IO operations sa Main-dispatcher — hinaharangan nito ang UI
  • Huwag patakbuhin ang mga gawaing CPU-intensive sa IO-dispatcher — hindi mahusay na ginagamit nito ang mga thread ng IO pool
  • Gamitin ang limitedParallelism para kontrolin ang paralelismo sa malawakang IO operations
  • Ilipat ang dispatcher gamit ang withContext, hindi sa paggawa ng bagong scope
  • Manahin ang dispatcher mula sa scope, kung ang coroutine ay hindi nangangailangan ng partikular na pool

Para sa mga kumplikadong senaryo, pagsamahin ang mga dispatcher gamit ang operator na +: Dispatchers.IO + SupervisorJob() + CoroutineExceptionHandler. Lumilikha ito ng CoroutineContext na may tinukoy na dispatcher, paghawak ng error, at nakahiwalay na hierarchy ng Job.

Mga Madalas Itanong

Ano ang pagkakaiba ng Dispatchers.IO at Dispatchers.Default?

Dispatchers.IO ay gumagamit ng pool hanggang 64 na thread para sa I/O-bound operations (paghihintay ng input-output), at Dispatchers.Default — pool ayon sa bilang ng CPU cores para sa mga gawaing pangkalkulasyon. Kapag kulang ang thread, ang parehong pool ay maaaring magbahagi ng thread sa isa't isa.

Maaari ba akong lumikha ng sarili kong dispatcher sa Kotlin Coroutines?

Oo, gamitin ang newSingleThreadContext() para sa single-thread o newFixedThreadPoolContext() para sa nakapirming pool. Para sa produksyon, gamitin ang limitedParallelism() batay sa mga umiiral na dispatcher — ito ay mas epektibo kaysa sa paggawa ng mga bagong pool.

Ano ang mangyayari kapag tinawag ang Dispatchers.Main sa background thread?

Kung hindi available ang Dispatchers.Main (halimbawa, sa JUnit test o background service), itatapon ang IllegalStateException. Para sa pagsubok, gamitin ang TestCoroutineDispatcher, para sa background services — Dispatchers.IO o Default.

Paano lilimitahan ang bilang ng parallel IO operations?

Gamitin ang Dispatchers.IO.limitedParallelism(N), kung saan N ang maximum na bilang ng parallel thread. Pinipigilan nito ang pagkaubos ng pool sa malawakang kahilingan at nagbibigay ng kontroladong paralelismo.

Kailan gagamitin ang Dispatchers.Unconfined?

Dispatchers.Unconfined ay angkop para sa mga pansamantalang operasyon: magaan na pagbabago ng data bago ipadala sa ibang dispatcher, mga senaryo ng pagsubok. Sa production code ng Android ay hindi inirerekomenda dahil sa hindi tiyak na thread ng pagpapatupad pagkatapos ng pagsususpinde.

Buod

  • Dispatchers — mga bahagi ng CoroutineContext na tumutukoy sa mga thread ng pagpapatupad ng coroutine
  • Dispatchers.Main — para sa Android UI operations, isang pangunahing thread
  • Dispatchers.IO — para sa network at disk operations, pool hanggang 64 na thread
  • Dispatchers.Default — para sa CPU-intensive computations, pool ayon sa bilang ng mga core
  • Dispatchers.Unconfined — walang pagkakatali sa thread, para sa pansamantalang operasyon
  • withContext — pangunahing mekanismo para sa paglipat sa pagitan ng mga dispatcher sa loob ng coroutine
  • Ang maling pagpili ng dispatcher ay humahantong sa UI lag o hindi mahusay na paggamit ng mga mapagkukunan

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din