runBlocking — mi ez, blokkoló híd és hogyan működik

Szerző: IT Sectr Megjelenés: 2026-06-22 Olvasási idő: 7 perc

runBlocking — Coroutine Builder Kotlinban, amely blokkolja az aktuális szálat az átadott korutin befejezéséig. A launch és async függvényektől eltérően nem suspend-függvény, és hagyományos (blokkoló) kódból is meghívható. A JetBrains dokumentációja szerint, 2024, a runBlocking hídként szolgál a szinkron és aszinkron világ között, lehetővé téve korutinok indítását a main-függvényből és tesztekből.

Főbb pontok

  • runBlocking — blokkoló builder, amely létrehoz egy CoroutineScope-ot és vár a korutin befejeződésére
  • Szál blokkolása — a runBlocking visszatartja az aktuális szálat a korutin és az összes gyermekkorutin teljes befejezéséig
  • Belépési pontok — main(), JUnit-tesztek és híd a blokkoló és aszinkron kód között
  • Tilos az Android Main-Thread-en — a runBlocking meghívása az UI-szálon ANR-t okoz
  • Alternatívák — lifecycleScope, viewModelScope, TestCoroutineDispatcher Androidhoz

Mi az a runBlocking?

runBlocking — egy Kotlin-függvény, amely új CoroutineScope-ot hoz létre és elindítja az átadott korutint, blokkolva az aktuális szálat annak teljes befejezéséig. Az összes többi Coroutine Builder-től eltérően a runBlocking nem suspend-függvény, és hagyományos szinkron kódból is meghívható. A runBlocking aláírása egy CoroutineContext-et és egy suspend-blokkot fogad el, és T típusú eredményt ad vissza.

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

A runBlocking egy új eseményhurkot (event-loop) indít az aktuális szálban. Amikor a korutin meghív egy suspend-függvényt (pl. delay() vagy await()), a runBlocking blokkolja a szálat és más ütemezett korutinokat hajt végre ugyanabban a szálban a felfüggesztett korutin folytatásáig. Ez kooperatív blokkolás — a szál nem tétlenkedik, hanem más korutinokat dolgoz fel.

Hogyan működik a runBlocking

A runBlocking belső mechanizmusa eseményhurokon alapul: suspend-függvény meghívásakor a runBlocking felfüggeszti az aktuális blokk végrehajtását és más korutinokat indít a sorból. Amikor a suspend-függvény befejeződik, a végrehajtás folytatódik. Ez a ciklus addig tart, amíg az összes korutin be nem fejeződik.

Az event-loop belülről

A runBlocking a saját egyszálú poolját használja a korutinok végrehajtására. A Dispatchers.IO-tól vagy Default-tól eltérően a runBlocking nem vált szálat — az összes korutint az aktuális szálban dolgozza fel, váltogatva a végrehajtásukat. Ez az egyetlen builder, amely garantálja a végrehajtást ugyanabban a szálban.

kotlin
fun main() {
    val threadName = Thread.currentThread().getName()
    println("runBlocking előtt ezen a szálon: $threadName")

    val result = runBlocking {
        println("runBlocking-en belül ezen a szálon: ${Thread.currentThread().getName()}")
        delay(500L)
        "Done"
    }

    println("runBlocking után: $result")
}

A kimenet megmutatja, hogy mindhárom println ugyanazon a szálon fut. A runBlocking nem vált szálat, hanem eseményhurok segítségével kooperatív többfeladatos munkát szervez egy szálon belül.

Mikor használjuk a runBlocking

A runBlocking három esetben indokolt: a main() belépési pont konzolos alkalmazásokban, a suspend-függvények egységtesztelése és híd — suspend-kód meghívása callback-alapú vagy blokkoló könyvtárakból. Android production kódban a fő szálon történő használat szigorúan tilos.

ForgatókönyvAlkalmazhatóságKockázatok
main() konzolalkalmazásIgenNincs — ez a belépési pont, a szál nem blokkol UI-t
JUnit tesztekIgenMinimális — a tesztek definíció szerint szinkronok
Android UI-ThreadNemANR, késések, a felület lefagyása
Callback → CoroutineIgen, óvatosanSzálpool blokkolása hosszú műveleteknél

Android tesztekhez használj kotlinx-coroutines-test-et TestDispatcher-rel a runBlocking helyett. Ez időbeli vezérlést, automatikus visszaállítást és tesztizolációt biztosít.

A runBlocking alternatívái

A legtöbb esetben a runBlocking helyettesíthető és helyettesítendő aszinkron alternatívákkal. Android esetében ezek a viewModelScope, a lifecycleScope vagy a CoroutineScope megfelelő diszpécserrel. Tesztekhez — TestCoroutineDispatcher és runTest.

kotlin
    // Rossz: runBlocking az Android fő szálán
runBlocking(Dispatchers.Main) {
    val result = networkApi.fetchData()
    textView.setText(result)
}

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

A tesztek helyettesítője a runTest a kotlinx-coroutines-test-ből. Virtuális idővel rendelkező TestCoroutineScope-ot hoz létre, lehetővé téve a késleltetések tesztelését valódi várakozás nélkül. Ez felgyorsítja a teszteket és determinisztikussá teszi azokat.

Példák a runBlocking használatára

A leggyakoribb eset — suspend-függvények tesztelése. A runBlocking a tesztekben lehetővé teszi a korutin eredményének szinkron megvárását anélkül, hogy megváltoztatná az architektúrát. A második eset — callback API-val rendelkező könyvtárak, ahol a suspend-függvények blokkoló kontextusból kerülnek meghívásra a runBlocking segítségével.

kotlin
// Suspend függvény tesztelése runBlocking-gal
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)
    }
}

A callback és a suspend világ közötti hídként használj CompletableDeferred-et runBlocking kombinációban a callback-ek helyett — ez leegyszerűsíti az aszinkron műveletek láncait és javítja a kód olvashatóságát.

A helytelen használat veszélyei

A runBlocking helytelen használata gyakori hiba a blokkoló megközelítésről korutinokra való áttéréskor. Főbb problémák: meghívás az Android Main-Thread-en, runBlocking egymásba ágyazása, használat aszinkron függvényeken belül és hosszú műveletek indítása runBlocking segítségével.

  • ANR — a runBlocking az Android Main-Thread-en több mint 5 másodpercre blokkolja az UI megjelenítését
  • Deadlock — beágyazott runBlocking egy korutinban ugyanazon a szálon kölcsönös blokkoláshoz vezet
  • Zavar a diszpécserekkel — a Dispatchers.Main a runBlocking-en belül egy háttérszálon nem rendelkezik Looper-rel és kivétellel összeomlik
  • Memóriaszivárgás — a runBlocking nem szakad meg automatikusan az Activity/Fragment megsemmisülésekor

Aranyszabály: a runBlocking egy híd, nem helyettesítés. Csak a blokkoló és nem blokkoló világok összekötésére használjuk. Minden más feladathoz alkalmazzuk a launch, async vagy lifecycleScope függvényeket.

Gyakran Ismételt Kérdések

Miért blokkolja a runBlocking a szálat, míg más builderek nem?

runBlocking az egyetlen builder, amely nem suspend-függvény. Eseményhurkot indít az aktuális szálban, és nem adja vissza a vezérlést, amíg az összes korutin be nem fejeződött. A launch és async azonnal visszaadják a vezérlést, a korutint a háttérben futtatva.

Használható a runBlocking Android ViewModel-ben?

Nem ajánlott. A ViewModel beépített viewModelScope-pal rendelkezik, amely automatikusan kezeli a korutinokat és megszakítja azokat megsemmisüléskor. A runBlocking a ViewModel-ben blokkolja a szálat és nem reagál a lifecycle megszakítására.

Mivel helyettesítsem a runBlocking-et egységtesztekben?

Használd a runTest-et a kotlinx-coroutines-test könyvtárból. Virtuális idővezérléssel, automatikus megszakítással és determinisztikus végrehajtással rendelkező TestCoroutineScope-ot biztosít.

Mi az event-loop a runBlocking-ben?

Event-loop — az eseményfeldolgozási ciklus a runBlocking-en belül. Amikor egy korutin felfüggesztésre kerül (pl. delay()), az event-loop átvált más kész korutinok végrehajtására ugyanabban a szálban. Ez a többfeladatos munka illúzióját kelti szálváltás nélkül.

Mi történik, ha a runBlocking-et runBlocking-en belül hívjuk meg?

Beágyazott runBlocking egy szálban deadlock-ot hoz létre — a külső blokk vár a belsőre, de a belső nem kezdődhet el, amíg a külső be nem fejeződik. Különböző szálakban ez elfogadható, de a hibakeresés nehézsége miatt erősen nem ajánlott.

Összefoglalás

  • runBlocking — blokkoló Coroutine Builder, híd a blokkoló és aszinkron kód között
  • Event-loop a runBlocking kooperatívan dolgozza fel a korutinokat egy szálban váltás nélkül
  • Engedélyezett esetek — main(), JUnit tesztek, híd callback könyvtárakból
  • Tiltott esetek — Android UI-Thread, beágyazott hívások, hosszú műveletek
  • Alternatívák — lifecycleScope, viewModelScope, runTest tesztekhez
  • ANR kockázat — a runBlocking a Main-Thread-en 5 másodperc után az alkalmazás lefagyását okozza
  • Android production kódhoz használj aszinkron buildereket — a runBlocking nem UI-ra való

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is