Kotlin Academy · Lektion

SupervisorJob vs. Job: Fehlerisolierung

Verwenden Sie SupervisorJob, damit der Fehler eines Kindes nicht zum Abbruch der Geschwister führt.

Lektion 1 von 413 Schritte

SupervisorJob vs. Job: Fehlerisolierung ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Standardmäßige Weitergabe von Job-Fehlern

Bei einem regulären Job bricht ein Fehler eines Childs den Parent ab, der wiederum alle Geschwister abbricht. Ein einziger Fehler bringt die gesamte Hierarchie zum Erliegen.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch { delay(50); throw RuntimeException("child 1 failed") }
            launch { delay(1000); println("child 2 — never prints") }
        }
    } catch (e: RuntimeException) {
        println("Caught: ${e.message}")
    }
}

Überblick über SupervisorJob

SupervisorJob ändert diese Regel: Ein Fehler eines Childs bricht die Geschwister oder den Parent NICHT ab. Jedes Child schlägt unabhängig von den anderen fehl.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val supervisor = SupervisorJob()
    val scope = CoroutineScope(coroutineContext + supervisor)
    scope.launch { throw RuntimeException("child 1 failed") }
    scope.launch { delay(100); println("child 2 still runs") }
    delay(200)
    supervisor.cancel()
}

supervisorScope-Builder

supervisorScope { } erstellt einen Scope mit einem SupervisorJob als Parent. Dies ist die idiomatische Methode, um unabhängige Childs auszuführen.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val job1 = launch {
            throw RuntimeException("job1 failed")
        }
        val job2 = launch {
            delay(100)
            println("job2 succeeded")
        }
        job1.join()  // wait for job1 (it failed)
        job2.join()  // job2 is unaffected
    }
}

Fehler von Childs abfangen

Mit supervisorScope behandelt jedes Child seine eigene Exception. Nicht behandelte Exceptions in Childs müssen für jedes Child einzeln abgefangen werden.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        val result = async {
            delay(50)
            throw RuntimeException("async failed")
        }
        try {
            result.await()
        } catch (e: RuntimeException) {
            println("Caught from async: ${e.message}")
        }
        println("Scope continues")
    }
}

Job vs. SupervisorJob beim Erstellen eines Scopes

Übergeben Sie beim Erstellen eines CoroutineScopes für einen Service oder ein ViewModel, das einzelne Fehler von Childs überstehen soll, SupervisorJob().

import kotlinx.coroutines.*
class MyService {
    private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
    fun startTask(name: String) {
        scope.launch {
            if (name == "fail") throw RuntimeException("$name failed")
            println("$name done")
        }
    }
    fun stop() = scope.cancel()
}
fun main() = runBlocking {
    val svc = MyService()
    svc.startTask("fail")
    svc.startTask("ok")
    delay(100)
    svc.stop()
}

viewModelScope verwendet SupervisorJob

Der Android-viewModelScope basiert auf einem SupervisorJob. Ein fehlgeschlagener launch-Aufruf bricht die anderen Coroutines des ViewModels nicht ab.

import kotlinx.coroutines.*
// Android ViewModel internals:
// val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
// Each launch is independent — one failure doesn't crash the ViewModel
fun main() = runBlocking {
    println("viewModelScope = SupervisorJob + Main")
}

Parallele Zerlegung mit supervisorScope

Verwenden Sie supervisorScope + async für parallele Aufgaben, bei denen einige fehlschlagen können, ohne die anderen zu beeinflussen.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val results = supervisorScope {
        val a = async { delay(50); "result-A" }
        val b = async { throw RuntimeException("B failed") }
        val c = async { delay(30); "result-C" }
        listOf(
            runCatching { a.await() },
            runCatching { b.await() },
            runCatching { c.await() }
        )
    }
    results.forEach { println(it) }
}

Wann Sie einen regulären Job verwenden

Verwenden Sie einen regulären Job (coroutineScope), wenn alle untergeordneten Coroutines gemeinsam erfolgreich sein müssen – ein Fehler sollte die gesamte Gruppe abbrechen. Wie bei einer Transaktion: alles oder nichts.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {  // regular Job
            val a = async { delay(50); "A" }
            val b = async { throw RuntimeException("B failed") }
            println(a.await())
            println(b.await())  // throws — cancels a too
        }
    } catch (e: RuntimeException) {
        println("Transaction failed: ${e.message}")
    }
}

Weitergabe von Ausnahmen in supervisorScope

In supervisorScope wird eine Ausnahme nur dann an den Scope weitergegeben, wenn sie aus der obersten Ebene der untergeordneten Coroutine entweicht – also kein try-catch in der untergeordneten Coroutine vorhanden ist. Der übergeordnete Scope bekommt sie nicht mit.

import kotlinx.coroutines.*
fun main() = runBlocking {
    supervisorScope {
        // Exception caught inside child — scope unaffected
        launch {
            try { throw RuntimeException("handled") }
            catch (e: Exception) { println("Child caught: ${e.message}") }
        }
        delay(100)
        println("Scope survived")
    }
}

CoroutineExceptionHandler mit SupervisorJob

Installieren Sie einen CoroutineExceptionHandler in einem Supervisor-Scope, um nicht abgefangene Fehler untergeordneter Coroutines zu protokollieren oder darauf zu reagieren, ohne den Scope zum Absturz zu bringen.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, e ->
        println("Uncaught: ${e.message}")
    }
    val scope = CoroutineScope(SupervisorJob() + handler)
    scope.launch { throw RuntimeException("unhandled failure") }
    scope.launch { delay(100); println("still running") }
    delay(200)
    scope.cancel()
}

Zusammenfassung der Fehlerisolierung

Job: Eine untergeordnete Coroutine schlägt fehl → alle schlagen fehl. SupervisorJob: Untergeordnete Coroutines schlagen unabhängig voneinander fehl. Verwenden Sie einen Supervisor für Services und ViewModels und einen regulären Job für Transaktionsgruppen.

import kotlinx.coroutines.*
// Decision table:
// coroutineScope { }   -> Job: all-or-nothing
// supervisorScope { }  -> SupervisorJob: independent failures
// CoroutineScope(SupervisorJob()) -> long-lived service
fun main() = runBlocking { println("Pick the right job for the right scope") }

Kurze Überprüfung

Welcher Scope verhindert, dass der Fehler einer untergeordneten Coroutine deren Geschwister-Coroutines abbricht?

Zusammenfassung

Job: Ein Fehler breitet sich auf Geschwister-Coroutines aus. SupervisorJob/supervisorScope: Fehler sind auf die jeweilige untergeordnete Coroutine begrenzt. Verwenden Sie supervisorScope für parallele unabhängige Aufgaben und coroutineScope für Transaktionsgruppen.

Kostenlos starten

Lerne Kotlin mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
51
Lektionen
203

Häufig gestellte Fragen

Ist die Lektion „SupervisorJob vs. Job: Fehlerisolierung“ kostenlos?

Ja — der vollständige Text von „SupervisorJob vs. Job: Fehlerisolierung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „SupervisorJob vs. Job: Fehlerisolierung“?

Verwenden Sie SupervisorJob, damit der Fehler eines Kindes nicht zum Abbruch der Geschwister führt. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Kotlin Academy zu starten?

Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „SupervisorJob vs. Job: Fehlerisolierung“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?

Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. SupervisorJob vs. Job: Fehlerisolierung
  2. CoroutineExceptionHandler: globaler Handler für unbehandelte Exceptions
  3. Exception-Weitergabe bei async/await
  4. Robuste Coroutine-Architekturen entwerfen
← Zurück zu Kotlin Academy