runBlocking — nedir, bloklayıcı köprü ve nasıl çalışır

Yazar: IT Sectr Yayınlanma: 2026-06-22 Okuma süresi: 7 dk

runBlocking — Kotlin'de, iletilen koroutin tamamlanana kadar mevcut iş parçacığını bloke eden bir Coroutine Builder'dır. launch ve async'in aksine, bir suspend fonksiyonu değildir ve normal (bloklayıcı) koddan çağrılabilir. JetBrains belgeleri, 2024'ne göre, runBlocking senkron ve asenkron dünyalar arasında bir köprü görevi görerek main fonksiyonundan ve testlerden koroutin başlatılmasına olanak tanır.

Ana Noktalar

  • runBlocking — bir CoroutineScope oluşturan ve koroutinin tamamlanmasını bekleyen bloklayıcı bir oluşturucu
  • İş parçacığı bloklama — runBlocking, koroutin ve tüm alt koroutinler tamamen bitene kadar mevcut iş parçacığını tutar
  • Giriş noktaları — main(), JUnit testleri ve bloklayıcı ile asenkron kod arasında köprü
  • Android ana iş parçacığında yasak — UI iş parçacığında runBlocking çağırmak ANR'ye neden olur
  • Alternatifler — Android için lifecycleScope, viewModelScope, TestCoroutineDispatcher

runBlocking nedir?

runBlocking, yeni bir CoroutineScope oluşturan ve iletilen koroutini çalıştıran, tamamen bitene kadar mevcut iş parçacığını bloke eden bir Kotlin fonksiyonudur. Diğer tüm Coroutine Builder'ların aksine, runBlocking bir suspend fonksiyonu değildir ve sıradan senkron koddan çağrılabilir. runBlocking'in imzası bir CoroutineContext ve bir suspend bloğu alır, T türünde bir sonuç döndürür.

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

runBlocking, mevcut iş parçacığında yeni bir event-loop başlatır. Koroutin bir suspend fonksiyonunu (örneğin, delay() veya await()) çağırdığında, runBlocking iş parçacığını bloke eder ve askıya alınan koroutin devam edene kadar aynı iş parçacığında diğer planlanmış koroutinleri çalıştırır. Bu işbirlikçi bloklamadır — iş parçacığı boşta değil, diğer koroutinleri işler.

runBlocking nasıl çalışır

runBlocking'in iç mekanizması bir event-loop'a dayanır: bir suspend fonksiyonu çağrıldığında, runBlocking mevcut bloğun yürütülmesini duraklatır ve kuyruktan diğer koroutinleri çalıştırır. Suspend fonksiyonu tamamlandığında, yürütme devam eder. Bu döngü tüm koroutinler bitene kadar devam eder.

Event-loop'un iç yüzü

runBlocking, koroutinleri yürütmek için kendi tek iş parçacıklı havuzunu kullanır. Dispatchers.IO veya Default'un aksine, runBlocking iş parçacıklarını değiştirmez — tüm koroutinleri mevcut iş parçacığında işler, yürütmelerini iç içe geçirir. Bu, aynı iş parçacığında yürütmeyi garanti eden tek oluşturucudur.

kotlin
fun main() {
    val threadName = Thread.currentThread().getName()
    println("runBlocking öncesi $threadName üzerinde")

    val result = runBlocking {
        println("runBlocking içinde ${Thread.currentThread().getName()} üzerinde")
        delay(500L)
        "Done"
    }

    println("runBlocking sonrası: $result")
}

Çıktı, her üç println ifadesinin de aynı iş parçacığında yürütüldüğünü gösterecektir. runBlocking iş parçacıklarını değiştirmez, bir event-loop kullanarak tek bir iş parçacığı içinde işbirlikçi çoklu görev düzenler.

runBlocking ne zaman kullanılır

runBlocking üç senaryoda haklı çıkar: konsol uygulamalarında main() giriş noktası, suspend fonksiyonlarının birim testleri ve köprü — callback tabanlı veya bloklayıcı kütüphanelerden suspend kod çağrısı. Üretim Android kodunda, ana iş parçacığında kullanımı kesinlikle yasaktır.

SenaryoUygulanabilirlikRiskler
main() konsol uygulamasınınEvetYok — giriş noktasıdır, iş parçacığı UI'ı bloke etmez
JUnit testleriEvetMinimal — testler tanım gereği senkrondur
Android UI iş parçacığıHayırANR, gecikmeler, arayüz donması
Callback → CoroutineEvet, dikkatleUzun işlemlerde iş parçacığı havuzu blokajı

Android testleri için, runBlocking yerine kotlinx-coroutines-test ile TestDispatcher kullanın. Bu, zaman kontrolü, otomatik temizlik ve test izolasyonu sağlar.

runBlocking alternatifleri

Çoğu senaryoda, runBlocking asenkron alternatiflerle değiştirilebilir ve değiştirilmelidir. Android için bunlar viewModelScope, lifecycleScope veya uygun dispatcher ile CoroutineScope'dur. Testler için — TestCoroutineDispatcher ve runTest.

kotlin
    // Kötü: Android ana iş parçacığında runBlocking
runBlocking(Dispatchers.Main) {
    val result = networkApi.fetchData()
    textView.setText(result)
}

// İyi: lifecycleScope
lifecycleScope.launch {
    val result = withContext(Dispatchers.IO) { networkApi.fetchData() }
    textView.setText(result)
}

Testler için alternatif, kotlinx-coroutines-test kütüphanesinden runTest'dir. Sanal zamanlı bir TestCoroutineScope oluşturur, gerçek bekleme olmadan gecikmeleri test etmeye olanak tanır. Bu, testleri hızlandırır ve belirleyici hale getirir.

runBlocking kullanım örnekleri

En yaygın senaryo, suspend fonksiyonlarını test etmektir. Testlerde runBlocking, mimariyi değiştirmeden bir koroutin sonucunu senkron olarak beklemenizi sağlar. İkinci senaryo, callback API'lerine sahip kütüphanelerdir; burada suspend fonksiyonları, runBlocking aracılığıyla bloklayıcı bir bağlamdan çağrılır.

kotlin
// runBlocking ile suspend fonksiyonunu 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 ve suspend dünyaları arasındaki köprü için, callbacks yerine runBlocking ile birlikte CompletableDeferred kullanın — bu, asenkron işlem zincirlerini basitleştirir ve kod okunabilirliğini artırır.

Yanlış kullanımın tehlikeleri

runBlocking'in yanlış kullanımı, bloklayıcı yaklaşımdan koroutinlere geçiş yaparken sık yapılan hatalardan biridir. Ana sorunlar: Android ana iş parçacığında çağrı, runBlocking'in iç içe geçirilmesi, asenkron fonksiyonlar içinde kullanımı ve runBlocking aracılığıyla uzun işlemlerin başlatılması.

  • ANR — Android ana iş parçacığında runBlocking, UI oluşturmayı 5 saniyeden fazla bloke eder
  • Deadlock — aynı iş parçacığında bir koroutin içinde iç içe runBlocking karşılıklı blokaj yaratır
  • Dispatcher karışıklığı — arka plan iş parçacığında runBlocking içindeki Dispatchers.Main'in Looper'ı yoktur ve istisna fırlatır
  • Bellek sızıntıları — Activity/Fragment yok edildiğinde runBlocking otomatik olarak iptal edilmez

Altın kural: runBlocking bir köprüdür, bir yedek değildir. Yalnızca bloklayıcı ve bloklayıcı olmayan dünyaları birbirine bağlamak için kullanın. Diğer tüm görevler için launch, async veya lifecycleScope kullanın.

Sıkça Sorulan Sorular

runBlocking iş parçacığını bloke ederken diğer oluşturucular neden etmez?

runBlocking, suspend fonksiyonu olmayan tek oluşturucudur. Mevcut iş parçacığında bir event-loop başlatır ve tüm koroutinler tamamlanana kadar kontrolü geri vermez. launch ve async hemen kontrolü geri verir, koroutini arka planda çalıştırır.

Android ViewModel'de runBlocking kullanılabilir mi?

Önerilmez. ViewModel, koroutinleri otomatik olarak yöneten ve yok edildiğinde iptal eden yerleşik bir viewModelScope'a sahiptir. ViewModel'de runBlocking iş parçacığını bloke eder ve yaşam döngüsü iptaline yanıt vermez.

Birim testlerde runBlocking yerine ne kullanılmalı?

kotlinx-coroutines-test kütüphanesinden runTest kullanın. Sanal zaman kontrolü, otomatik iptal ve belirleyici yürütme ile TestCoroutineScope sağlar.

runBlocking'de event-loop nedir?

Event-loop, runBlocking içindeki bir olay işleme döngüsüdür. Bir koroutin askıya alındığında (ör: delay()), event-loop aynı iş parçacığında diğer hazır koroutinleri çalıştırmaya geçer. Bu, iş parçacığı değiştirmeden çoklu görev yanılsaması yaratır.

runBlocking içinde runBlocking çağrılırsa ne olur?

Aynı iş parçacığında iç içe runBlocking bir deadlock yaratır — dış blok içtekini bekler, ancak içteki dıştaki bitene kadar başlayamaz. Farklı iş parçacıklarında izin verilir ancak hata ayıklama karmaşıklığı nedeniyle kesinlikle önerilmez.

Özet

  • runBlocking — bloklayıcı bir Coroutine Builder, bloklayıcı ve asenkron kod arasında köprü
  • Event-loop runBlocking, değiştirmeden tek bir iş parçacığında işbirlikçi olarak koroutinleri işler
  • İzin verilen senaryolar — main(), JUnit testleri, callback kütüphanelerinden köprü
  • Yasak senaryolar — Android UI iş parçacığı, iç içe çağrılar, uzun işlemler
  • Alternatifler — lifecycleScope, viewModelScope, testler için runTest
  • ANR riski — ana iş parçacığında runBlocking, 5 saniye sonra uygulamayı dondurur
  • Üretim Android kodu için asenkron oluşturucular kullanın — runBlocking UI için tasarlanmamıştır

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun