Dispatchers — əsas anlayışlar, dispatçer növləri və onların iş prinsipi

Müəllif: IT Sectr Dərc olunub: 2026-06-22 Oxuma vaxtı: 9 dəq

Dispatchers Kotlin Coroutines-də — CoroutineContext komponentləri olub, korutinlərin icrası üçün iplikləri təyin edir: Main (UI-ipliyi), IO (şəbəkə və disk), Default (CPU-intensiv tapşırıqlar) və Unconfined (cari iplik). Hər bir dispatçer xüsusi iş növü üçün optimallaşdırılmış ixtisaslaşmış iplik hovuzunu idarə edir. JetBrains, 2024 təlimatına görə, düzgün dispatçer seçimi tətbiqin performansı və sabitliyi üçün vacibdir.

Əsas məqamlar

  • Dispatchers — tapşırıqların ipliklər üzrə paylanmasını idarə edən əvvəlcədən təyin edilmiş korutin dispatçerləri
  • Dispatchers.Main — Android UI-ipliyi, interfeysin yenilənməsi və View ilə iş üçün
  • Dispatchers.IO — şəbəkə sorğuları, faylların oxunması/yazılması və verilənlər bazası üçün hovuz (64 iplikdək)
  • Dispatchers.Default — prosessor nüvələrinin sayına görə CPU-intensiv tapşırıqlar üçün hovuz
  • Dispatchers.Unconfined — keçidsiz, cari ipliyin miras alınması

Dispatchers nədir?

Dispatchers — CoroutineDispatcher interfeysinin implementasiyaları olub, CoroutineContext elementləridir. Onlar korutinanın hansı iplikdə və ya iplik hovuzunda icra olunacağını təyin edir. launch və ya async vasitəsilə korutina yaradılarkən dispatçer ilk parametr kimi ötürülə bilər: launch(Dispatchers.IO) { ... }. Dispatçer göstərilməzsə, xarici CoroutineScope-dan miras alınır.

Kotlin dörd daxili dispatçer təqdim edir: Main, IO, Default, Unconfined. Hər bir dispatçer müəyyən əməliyyat növü üçün optimallaşdırılmış öz iplik hovuzundan istifadə edir. Düzgün dispatçer seçimi tətbiqin performansını müəyyən edir: səhv seçim interfeys ləngimələrinə, CPU nüvələrinin boş qalmasına və ya ipliklərin səmərəsiz istifadəsinə səbəb olur.

Dispatçerİplik hovuzuMaks. iplikTətbiq
Dispatchers.MainBir (UI)1UI yeniləmə, LiveData, View
Dispatchers.IOIO hovuzu64 (limitedParallelism)Şəbəkə, fayllar, verilənlər bazası
Dispatchers.DefaultCPU hovuzuN nüvəÇeşidləmə, parsering, hesablamalar
Dispatchers.UnconfinedCari iplikYoxAralıq əməliyyatlar, testlər

Dispatchers.Main: UI-ipliyi

Dispatchers.Main — Android-in əsas ipliyində korutinləri icra edən dispatçer. İnterfeyslə bağlı əməliyyatlar üçün nəzərdə tutulub: TextView yeniləmə, notifyDataSetChanged çağırışı, LiveData və StateFlow ilə iş. Android-də bu dispatçer Handler (Looper.getMainLooper()) vasitəsilə implementasiya olunub.

kotlin
// UI yeniləmələri üçün Main-ə düzgün keçid
viewModelScope.launch(Dispatchers.IO) {
    val data = repository.fetchData()
    withContext(Dispatchers.Main) {
        _uiState.value = data
    }
}

Korutina artıq Main-dispatçerindədirsə, əlavə withContext(Dispatchers.Main) əlavə yük yaratmır — dispatçer cari ipliyi yoxlayır və keçidi buraxır. withContext dispatçerlər arasında keçid üçün üstünlük verilən üsuldur.

Dispatchers.IO: şəbəkə və disk əməliyyatları

Dispatchers.IO — giriş-çıxış əməliyyatları üçün optimallaşdırılmış dispatçer: HTTP sorğuları (Ktor, OkHttp), faylların oxunması və yazılması, Room və ya SQLDelight ilə iş. O, standart olaraq 64 iplikdən ibarət hovuzdan istifadə edir, yük altında miqyaslanır. Hər yeni IO sorğusu limitə çatana qədər əlavə iplik yarada bilər.

Paralelliyin məhdudlaşdırılması

Eyni vaxtda IO əməliyyatlarının sayını idarə etmək üçün limitedParallelism() istifadə edin. Bu funksiya paralel ipliklərin sayını məhdudlaşdıran yeni dispatçer yaradır, kütləvi əməliyyatlarda hovuzun tükənməsinin qarşısını alır.

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

// 4 paralel əməliyyat limiti ilə 100 faylı yüklə
coroutineScope {
    val files = (1..100).map { index ->
        async(limitedIo) {
            downloadFile("file_$index")
        }
    }
    files.awaitAll()
}

Korutinanın gözləmədə vaxt keçirdiyi bütün əməliyyatlar (I/O-bound) üçün IO-dispatçerindən istifadə edin. IO-dispatçerində CPU-intensiv tapşırıqlar səmərəsizdir — onlar giriş-çıxış üçün nəzərdə tutulmuş iplikləri tutur, sistemin ötürmə qabiliyyətini azaldır.

Dispatchers.Default: CPU-intensiv tapşırıqlar

Dispatchers.Default — prosessoru yükləyən hesablama əməliyyatları üçün dispatçer: çeşidləmə, filtrləmə, JSON parseringi (Moshi, Kotlinx Serialization), şəkillərin işlənməsi, hesablamalar. Hovuzun ölçüsü prosessor nüvələrinin sayına bərabərdir (lakin 2-dən az deyil). Bu, kontekst dəyişmədən CPU-nun maksimum yüklənməsini təmin edir.

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

IO əməliyyatları üçün Dispatchers.Default istifadə etməyin — bu, hesablama tapşırıqlarını emal edə biləcək CPU hovuzu ipliklərini bloklayacaq. IO və Default-a bölünmə sistem resurslarından optimal istifadə etməyə imkan verir: IO iplikləri giriş-çıxışı gözləyir, CPU iplikləri daim hesablamalarla məşğuldur.

Dispatchers.Unconfined: cari iplik

Dispatchers.Unconfined — korutinanı heç bir hovuza bağlamayan xüsusi dispatçer. Korutina launch/async çağırıldığı iplikdə icraya başlayır və dayandırıldıqdan sonra resume-i çağıran iplikdə bərpa olunur. Bu davranış sabit kontekst tələb etməyən aralıq əməliyyatlar üçün uyğundur.

kotlin
fun main() = runBlocking {
    launch(Dispatchers.Unconfined) {
        println("Gecikmədən əvvəl: ${Thread.currentThread().getName()}")
        delay(500L)
        println("Gecikmədən sonra: ${Thread.currentThread().getName()}")
    }
}

Production kodda Dispatchers.Unconfined nadir hallarda tətbiq olunur. Əsas hallar: məlumatları başqa dispatçerə ötürməzdən əvvəl yüngül transformasiyalar və testlər. Production yükü üçün aşkar dispatçerlərdən istifadə edin — Unconfined gözlənilməzdir, çünki icra ipliyi resume implementasiyasından asılıdır.

Dispatçeri necə seçməli

Dispatçer seçimi tapşırıq növü ilə müəyyən edilir: UI əməliyyatları → Main, I/O-bound → IO, CPU-bound → Default, aralıq → scope-dan miras. Android üçün korutinanı əsas işin yerinə yetirildiyi dispatçerdə işə salmaq, UI yeniləməsindən əvvəl isə withContext vasitəsilə Main-ə keçmək tövsiyə olunur.

  • IO əməliyyatlarını Main-dispatçerində işə salmayın — bu UI-ni bloklayır
  • CPU-intensiv tapşırıqları IO-dispatçerində işə salmayın — bu, IO hovuzunun ipliklərini səmərəsiz istifadə edir
  • limitedParallelism istifadə edin kütləvi IO əməliyyatlarında paralelliyi idarə etmək üçün
  • Dispatçeri dəyişdirin withContext ilə, yeni scope yaratmaqla deyil
  • Dispatçeri scope-dan miras alın korutina xüsusi hovuz tələb etmirsə

Mürəkkəb ssenarilər üçün dispatçerləri + operatoru ilə birləşdirin: Dispatchers.IO + SupervisorJob() + CoroutineExceptionHandler. Bu, müəyyən edilmiş dispatçer, xəta idarəetməsi və təcrid olunmuş Job iyerarxiyası ilə CoroutineContext yaradır.

Tez-tez verilən suallar

Dispatchers.IO və Dispatchers.Default nə ilə fərqlənir?

Dispatchers.IO I/O-bound əməliyyatları (giriş-çıxış gözləməsi) üçün 64 iplikdək hovuzdan istifadə edir, Dispatchers.Default isə hesablama tapşırıqları üçün CPU nüvələrinin sayına görə hovuzdan. İplik çatışmazlığında hər iki hovuz bir-biri ilə iplikləri bölüşə bilər.

Kotlin Coroutines-də öz dispatçerimi yarada bilərəmmi?

Bəli, tək iplikli üçün newSingleThreadContext() və ya sabit hovuz üçün newFixedThreadPoolContext() istifadə edin. Production üçün mövcud dispatçerlər əsasında limitedParallelism() tətbiq edin — bu, yeni hovuzlar yaratmaqdan daha səmərəlidir.

Fon ipliyində Dispatchers.Main çağırılsa nə olar?

Dispatchers.Main mövcud deyilsə (məsələn, JUnit testində və ya fon xidmətində), IllegalStateException atılır. Testlər üçün TestCoroutineDispatcher, fon xidmətləri üçün Dispatchers.IO və ya Default istifadə edin.

Paralel IO əməliyyatlarının sayını necə məhdudlaşdırmaq olar?

Dispatchers.IO.limitedParallelism(N) istifadə edin, burada N — maksimum paralel iplik sayıdır. Bu, kütləvi sorğularda hovuzun tükənməsinin qarşısını alır və idarə olunan paralellik təmin edir.

Dispatchers.Unconfined nə vaxt istifadə olunmalıdır?

Dispatchers.Unconfined aralıq əməliyyatlar üçün uyğundur: məlumatların başqa dispatçerə ötürülməzdən əvvəl yüngül transformasiyası, test ssenariləri. Android production kodunda tövsiyə edilmir, çünki dayandırmadan sonra icra ipliyi qeyri-müəyyəndir.

Nəticə

  • Dispatchers — korutinlərin icra ipliklərini təyin edən CoroutineContext komponentləri
  • Dispatchers.Main — Android UI əməliyyatları üçün, bir əsas iplik
  • Dispatchers.IO — şəbəkə və disk əməliyyatları üçün, 64 iplikdək hovuz
  • Dispatchers.Default — CPU-intensiv hesablamalar üçün, nüvələrin sayına görə hovuz
  • Dispatchers.Unconfined — iplik bağlantısı olmadan, aralıq əməliyyatlar üçün
  • withContext — korutina daxilində dispatçerlər arasında keçidin əsas mexanizmi
  • Səhv dispatçer seçimi UI ləngimələrinə və ya resursların səmərəsiz istifadəsinə səbəb olur

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun