runBlocking — was es ist, blockierende Brücke und wie es funktioniert

Autor: IT Sectr Veröffentlicht: 2026-06-22 Lesezeit: 7 Min.

runBlocking — ein Coroutine Builder in Kotlin, der den aktuellen Thread blockiert, bis die übergebene Coroutine abgeschlossen ist. Anders als launch und async ist es keine suspend-Funktion und kann aus gewöhnlichem (blockierendem) Code aufgerufen werden. Laut der JetBrains-Dokumentation, 2024, dient runBlocking als Brücke zwischen der synchronen und asynchronen Welt und ermöglicht das Starten von Coroutinen aus der main-Funktion und Tests.

Wichtigste Erkenntnisse

  • runBlocking — ein blockierender Builder, der einen CoroutineScope erstellt und auf den Abschluss der Coroutine wartet
  • Thread-Blockierung — runBlocking hält den aktuellen Thread bis zum vollständigen Abschluss der Coroutine und aller untergeordneten Coroutinen
  • Einstiegspunkte — main(), JUnit-Tests und Brücken zwischen blockierendem und asynchronem Code
  • Verboten auf dem Hauptthread von Android — runBlocking auf dem UI-Thread verursacht ANR
  • Alternativen — lifecycleScope, viewModelScope, TestCoroutineDispatcher für Android

Was ist runBlocking?

runBlocking ist eine Kotlin-Funktion, die einen neuen CoroutineScope erstellt und die übergebene Coroutine startet, wobei der aktuelle Thread blockiert wird, bis sie vollständig abgeschlossen ist. Anders als alle anderen Coroutine Builder ist runBlocking keine suspend-Funktion und kann aus gewöhnlichem synchronem Code aufgerufen werden. Die Signatur von runBlocking nimmt einen CoroutineContext und einen suspend-Block entgegen und gibt ein Ergebnis vom Typ T zurück.

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

runBlocking startet eine neue Event-Loop auf dem aktuellen Thread. Wenn die Coroutine eine suspend-Funktion (z. B. delay() oder await()) aufruft, blockiert runBlocking den Thread und führt andere geplante Coroutinen auf demselben Thread aus, bis die angehaltene fortgesetzt wird. Dies ist kooperatives Blockieren — der Thread ist nicht untätig, sondern verarbeitet andere Coroutinen.

Wie runBlocking funktioniert

Der interne Mechanismus von runBlocking basiert auf einer Event-Loop: Beim Aufruf einer suspend-Funktion pausiert runBlocking die Ausführung des aktuellen Blocks und führt andere Coroutinen aus der Warteschlange aus. Wenn die suspend-Funktion abgeschlossen ist, wird die Ausführung fortgesetzt. Dieser Zyklus wiederholt sich, bis alle Coroutinen abgeschlossen sind.

Event-Loop unter der Haube

runBlocking verwendet einen eigenen Single-Thread-Pool zur Ausführung von Coroutinen. Anders als Dispatchers.IO oder Default wechselt runBlocking keine Threads — es verarbeitet alle Coroutinen auf dem aktuellen Thread und verschränkt ihre Ausführung. Dies ist der einzige Builder, der die Ausführung auf demselben Thread garantiert.

kotlin
fun main() {
    val threadName = Thread.currentThread().getName()
    println("Vor runBlocking auf $threadName")

    val result = runBlocking {
        println("Innerhalb von runBlocking auf ${Thread.currentThread().getName()}")
        delay(500L)
        "Done"
    }

    println("Nach runBlocking: $result")
}

Die Ausgabe zeigt, dass alle drei println-Anweisungen auf demselben Thread ausgeführt werden. runBlocking wechselt keine Threads, sondern organisiert kooperatives Multitasking innerhalb eines einzelnen Threads mithilfe einer Event-Loop.

Wann runBlocking verwenden

runBlocking ist in drei Szenarien gerechtfertigt: dem main()-Einstiegspunkt in Konsolenanwendungen, Komponententests für suspend-Funktionen und als Brücke — dem Aufruf von suspend-Code aus callback-basierten oder blockierenden Bibliotheken. In Produktions-Android-Code ist die Verwendung auf dem Hauptthread strengstens verboten.

SzenarioAnwendbarkeitRisiken
main() einer KonsolenanwendungJaKeine — es ist der Einstiegspunkt, der Thread blockiert keine UI
JUnit-TestsJaMinimal — Tests sind per Definition synchron
Android-UI-ThreadNeinANR, Verzögerungen, Einfrieren der Oberfläche
Callback → CoroutineJa, mit VorsichtThread-Pool-Blockierung bei langen Operationen

Für Android-Tests verwenden Sie kotlinx-coroutines-test mit TestDispatcher anstelle von runBlocking. Dies bietet Zeitkontrolle, automatische Bereinigung und Testisolierung.

Alternativen zu runBlocking

In den meisten Szenarien kann und sollte runBlocking durch asynchrone Alternativen ersetzt werden. Für Android sind dies viewModelScope, lifecycleScope oder CoroutineScope mit dem richtigen Dispatcher. Für Tests — TestCoroutineDispatcher und runTest.

kotlin
    // Schlecht: runBlocking auf dem Android-Hauptthread
runBlocking(Dispatchers.Main) {
    val result = networkApi.fetchData()
    textView.setText(result)
}

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

Für Tests ist der Ersatz runTest aus kotlinx-coroutines-test. Es erstellt einen TestCoroutineScope mit virtueller Zeit, sodass Verzögerungen ohne echtes Warten getestet werden können. Dies beschleunigt Tests und macht sie deterministisch.

Anwendungsbeispiele für runBlocking

Das häufigste Szenario ist das Testen von suspend-Funktionen. runBlocking in Tests ermöglicht es, synchron auf ein Coroutinen-Ergebnis zu warten, ohne die Architektur zu ändern. Das zweite Szenario sind Bibliotheken mit Callback-APIs, bei denen suspend-Funktionen aus einem blockierenden Kontext über runBlocking aufgerufen werden.

kotlin
// Suspend-Funktion mit runBlocking testen
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)
    }
}

Für die Brücke zwischen Callback- und suspend-Welten verwenden Sie CompletableDeferred in Kombination mit runBlocking anstelle von Callbacks — dies vereinfacht asynchrone Operationsketten und verbessert die Lesbarkeit des Codes.

Gefahren der Fehlanwendung

Die unsachgemäße Verwendung von runBlocking ist einer der häufigsten Fehler beim Übergang von einem blockierenden Ansatz zu Coroutinen. Hauptprobleme: Aufruf auf dem Android-Hauptthread, Verschachtelung von runBlocking, Verwendung innerhalb asynchroner Funktionen und Start langlaufender Operationen über runBlocking.

  • ANR — runBlocking auf dem Android-Hauptthread blockiert das UI-Rendering für mehr als 5 Sekunden
  • Deadlock — verschachteltes runBlocking innerhalb einer Coroutine auf demselben Thread führt zu gegenseitiger Blockierung
  • Dispatcher-Verwirrung — Dispatchers.Main innerhalb von runBlocking in einem Hintergrundthread hat keinen Looper und löst eine Ausnahme aus
  • Speicherlecks — runBlocking wird nicht automatisch abgebrochen, wenn Activity/Fragment zerstört wird

Goldene Regel: runBlocking ist eine Brücke, kein Ersatz. Verwenden Sie es nur, um blockierende und nicht-blockierende Welten zu verbinden. Für alle anderen Aufgaben verwenden Sie launch, async oder lifecycleScope.

Häufig gestellte Fragen

Warum blockiert runBlocking den Thread, andere Builder aber nicht?

runBlocking ist der einzige Builder, der keine suspend-Funktion ist. Es startet eine Event-Loop auf dem aktuellen Thread und gibt die Kontrolle erst zurück, wenn alle Coroutinen abgeschlossen sind. launch und async geben sofort die Kontrolle zurück und führen die Coroutine im Hintergrund aus.

Kann runBlocking im Android ViewModel verwendet werden?

Nicht empfohlen. ViewModel verfügt über einen integrierten viewModelScope, der Coroutinen automatisch verwaltet und bei Zerstörung abbricht. runBlocking im ViewModel blockiert den Thread und reagiert nicht auf den Lifecycle-Abbruch.

Was sollte anstelle von runBlocking in Komponententests verwendet werden?

Verwenden Sie runTest aus der Bibliothek kotlinx-coroutines-test. Es bietet einen TestCoroutineScope mit virtueller Zeitsteuerung, automatischem Abbruch und deterministischer Ausführung.

Was ist eine Event-Loop in runBlocking?

Event-Loop ist ein Ereignisverarbeitungszyklus innerhalb von runBlocking. Wenn eine Coroutine angehalten wird (z. B. delay()), wechselt die Event-Loop zur Ausführung anderer bereiter Coroutinen auf demselben Thread. Dies erzeugt die Illusion von Multitasking ohne Thread-Wechsel.

Was passiert, wenn runBlocking innerhalb von runBlocking aufgerufen wird?

Verschachteltes runBlocking auf demselben Thread erzeugt einen Deadlock — der äußere Block wartet auf den inneren, aber der innere kann nicht beginnen, bis der äußere beendet ist. Auf verschiedenen Threads ist es erlaubt, aber aufgrund der Debugging-Komplexität stark abgeraten.

Zusammenfassung

  • runBlocking — ein blockierender Coroutine Builder, Brücke zwischen blockierendem und asynchronem Code
  • Event-Loop runBlocking verarbeitet Coroutinen kooperativ auf einem einzelnen Thread ohne Wechsel
  • Erlaubte Szenarien — main(), JUnit-Tests, Brücke aus Callback-Bibliotheken
  • Verbotene Szenarien — Android-UI-Thread, verschachtelte Aufrufe, langlaufende Operationen
  • Alternativen — lifecycleScope, viewModelScope, runTest für Tests
  • ANR-Risiko — runBlocking auf dem Hauptthread friert die App nach 5 Sekunden ein
  • Für Produktions-Android-Code verwenden Sie asynchrone Builder — runBlocking ist nicht für UI ausgelegt

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch