runBlocking — bu nədir, bloklayan körpü və necə işləyir

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

runBlocking — Kotlin dilində Coroutine Builder-dir, verilən korutinanın tamamlanmasına qədər cari thread-i bloklayır. launch və async-dən fərqli olaraq, o suspend-funksiya deyil və adi (bloklayan) koddan çağırıla bilər. JetBrains sənədlərinə görə, 2024, runBlocking sinxron və asinxron dünya arasında körpü rolunu oynayır, main-funksiyasından və testlərdən korutinaları işə salmağa imkan verir.

Əsas məqamlar

  • runBlocking — CoroutineScope yaradan və korutinanın tamamlanmasını gözləyən bloklayan bilder
  • Thread-in bloklanması — runBlocking korutina və bütün alt korutinalar tamamlanana qədər cari thread-i saxlayır
  • Giriş nöqtələri — main(), JUnit testləri və bloklayan ilə asinxron kod arasında körpü
  • Android Main-Thread-də qadağandır — UI thread-ində runBlocking çağırışı ANR-yə səbəb olur
  • Alternativlər — Android üçün lifecycleScope, viewModelScope, TestCoroutineDispatcher

runBlocking nədir?

runBlocking — Kotlin dilində yeni CoroutineScope yaradan və verilən korutinanı işə salan, onun tamamlanmasına qədər cari thread-i bloklayan funksiyadır. Bütün digər Coroutine Builder-lərdən fərqli olaraq, runBlocking suspend-funksiya deyil və adi sinxron koddan çağırıla bilər. runBlocking-in imzası CoroutineContext və suspend-blok qəbul edir, T tipli nəticə qaytarır.

kotlin
public fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> T
): T

runBlocking cari thread-də yeni event-loop işə salır. Korutina suspend-funksiya çağırdıqda (məsələn, delay() və ya await()), runBlocking thread-i bloklayır və dayandırılmış korutina bərpa olunana qədər eyni thread-də digər planlaşdırılmış korutinaları icra edir. Bu kooperativ bloklamadır — thread boş dayanmır, digər korutinaları emal edir.

runBlocking necə işləyir

runBlocking-in daxili mexanizmi event-loop-a əsaslanır: suspend-funksiya çağırıldıqda, runBlocking cari blokun icrasını dayandırır və növbədən digər korutinaları işə salır. Suspend-funksiya tamamlandıqda icra bərpa olunur. Bu dövr bütün korutinalar tamamlanana qədər davam edir.

Event-loop-un daxili quruluşu

runBlocking korutinaları icra etmək üçün öz təkthreadli hovuzundan istifadə edir. Dispatchers.IO və ya Default-dan fərqli olaraq, runBlocking thread-ləri dəyişmir — bütün korutinaları cari thread-də emal edir, onların icrasını növbələşdirir. Bu, eyni thread-də icraya zəmanət verən yeganə bilderdir.

kotlin
fun main() {
    val threadName = Thread.currentThread().getName()
    println("runBlocking-dən əvvəl $threadName")

    val result = runBlocking {
        println("runBlocking daxilində ${Thread.currentThread().getName()}")
        delay(500L)
        "Done"
    }

    println("runBlocking-dən sonra: $result")
}

Nəticə göstərəcək ki, hər üç println eyni thread-də icra olunur. runBlocking thread-i dəyişmir, əksinə event-loop vasitəsilə bir thread daxilində kooperativ çoxtapşırıqlılıq təşkil edir.

runBlocking nə vaxt istifadə edilməlidir

runBlocking üç ssenaridə əsaslandırılmışdır: konsol tətbiqlərində main() giriş nöqtəsi, suspend-funksiyaların vahid testləri və körpü — callback əsaslı və ya bloklayan kitabxanalardan suspend-kodun çağırılması. Android-in production-kodunda əsas thread-də istifadə qəti qadağandır.

SsenariTətbiq oluna bilərRisk
main() konsol tətbiqiBəliYoxdur — bu giriş nöqtəsidir, thread UI-ni bloklamır
JUnit testləriBəliMinimal — testlər tərifinə görə sinxrondur
Android UI-ThreadXeyrANR, gecikmələr, interfeysin donması
Callback → CoroutineBəli, ehtiyatlaUzun müddətli əməliyyatlarda thread hovuzunun bloklanması

Android testləri üçün runBlocking əvəzinə kotlinx-coroutines-test kitabxanasından TestDispatcher istifadə edin. Bu, vaxta nəzarət, avtomatik sıfırlama və test izolyasiyası təmin edir.

runBlocking alternativləri

Əksər ssenarilərdə runBlocking asinxron alternativlərlə əvəz edilə bilər və edilməlidir. Android üçün bunlar viewModelScope, lifecycleScope və ya düzgün dispetçerli CoroutineScope-dur. Testlər üçün — TestCoroutineDispatcher və runTest.

kotlin
    // Pis: Android əsas thread-də runBlocking
runBlocking(Dispatchers.Main) {
    val result = networkApi.fetchData()
    textView.setText(result)
}

// Yaxşı: lifecycleScope
lifecycleScope.launch {
    val result = withContext(Dispatchers.IO) { networkApi.fetchData() }
    textView.setText(result)
}

Testlər üçün əvəz runTest-dir kotlinx-coroutines-test kitabxanasından. O, virtual vaxt ilə TestCoroutineScope yaradır, gecikmələri real gözləmə olmadan test etməyə imkan verir. Bu testləri sürətləndirir və determinist edir.

runBlocking istifadə nümunələri

Ən çox yayılmış ssenari — suspend-funksiyaların test edilməsidir. Testlərdə runBlocking korutinanın nəticəsini sinxron gözləməyə imkan verir, arxitekturanı dəyişmədən. İkinci ssenari — callback API-si olan kitabxanalardır, burada suspend-funksiyalar runBlocking vasitəsilə bloklayan kontekstdən çağırılır.

kotlin
// Suspend funksiyasını runBlocking ilə test et
class RepositoryTest {
    @Test
    fun `fetchUser returns correct data`() {
        val repository = UserRepository(FakeApi())

        val result = runBlocking {
            repository.fetchUser("123")
        }

        assertEquals("John", result.name)
        assertEquals("john@test.com", result.email)
    }
}

Callback və suspend dünyası arasında körpü üçün callback-lər əvəzinə CompletableDeferred-i runBlocking ilə kombinasiyada istifadə edin — bu, asinxron əməliyyat zəncirlərini sadələşdirir və kodun oxunaqlılığını artırır.

Yanlış istifadənin təhlükələri

runBlocking-in yanlış istifadəsi bloklayan yanaşmadan korutinalara keçid zamanı ən çox rast gəlinən səhvlərdən biridir. Əsas problemlər: Android Main-Thread-də çağırış, runBlocking-in iç-içə yerləşdirilməsi, asinxron funksiyalar daxilində istifadə və runBlocking vasitəsilə uzun müddətli əməliyyatların işə salınması.

  • ANR — Android Main-Thread-də runBlocking UI renderini 5 saniyədən çox bloklayır
  • Deadlock — eyni thread-də korutina daxilində iç-içə runBlocking qarşılıqlı blokadaya səbəb olur
  • Dispetçerlərlə qarışıqlıq — fon thread-də runBlocking daxilində Dispatchers.Main Looper-ə malik deyil və xəta ilə nəticələnir
  • Yaddaş sızmaları — Activity/Fragment məhv olduqda runBlocking avtomatik ləğv edilmir

Qızıl qayda: runBlocking körpüdür, əvəz deyil. Yalnız bloklayan və bloklamayan dünyanı birləşdirmək üçün istifadə edin. Bütün digər tapşırıqlar üçün launch, async və ya lifecycleScope tətbiq edin.

Tez-tez verilən suallar

Niyə runBlocking thread-i bloklayır, digər bilderlər isə yox?

runBlocking suspend-funksiya olmayan yeganə bilderdir. O, cari thread-də event-loop işə salır və bütün korutinalar tamamlanana qədər nəzarəti qaytarmır. launch və async dərhal nəzarəti qaytarır, korutinanı fonda icra edir.

Android ViewModel-də runBlocking istifadə etmək olarmı?

Tövsiyə edilmir. ViewModel daxili viewModelScope-ə malikdir, o avtomatik korutinaları idarə edir və məhv olduqda ləğv edir. ViewModel-də runBlocking thread-i bloklayır və lifecycle ləğvinə reaksiya vermir.

Vahid testlərində runBlocking-i nə ilə əvəz etməli?

runTest kitabxanasından kotlinx-coroutines-test istifadə edin. O, virtual vaxta nəzarət, avtomatik ləğv və deterministik icra ilə TestCoroutineScope təmin edir.

runBlocking-də event-loop nədir?

Event-loop — runBlocking daxilində hadisələrin emal dövrüdür. Korutina dayandırıldıqda (məsələn, delay()), event-loop eyni thread-də digər hazır korutinaların icrasına keçir. Bu, thread-ləri dəyişmədən çox tapşırıqlılıq illüziyası yaradır.

runBlocking daxilində runBlocking çağırılsa nə olar?

Bir thread-də iç-içə runBlocking deadlock yaradır — xarici blok daxili gözləyir, lakin daxili xarici tamamlanana qədər başlaya bilməz. Müxtəlif thread-lərdə bu mümkündür, lakin debug çətinliyi səbəbindən qəti tövsiyə edilmir.

Nəticə

  • runBlocking — bloklayan Coroutine Builder, bloklayan və asinxron kod arasında körpü
  • Event-loop runBlocking korutinaları bir thread-də dəyişmədən kooperativ emal edir
  • İcazə verilən ssenarilər — main(), JUnit testləri, callback kitabxanalarından körpü
  • Qadağan olunmuş ssenarilər — Android UI-Thread, iç-içə çağırışlar, uzun müddətli əməliyyatlar
  • Alternativlər — lifecycleScope, viewModelScope, testlər üçün runTest
  • ANR riski — Main-Thread-də runBlocking 5 saniyədən sonra tətbiqin donmasına səbəb olur
  • Android production-kodu üçün asinxron bilderlərdən istifadə edin — runBlocking UI üçün nəzərdə tutulmayıb

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