Kotlin Academy · Lektion

Hur avbrytning sprids i coroutine-hierarkier

Förstå hur avbrytning sprids genom relationer mellan överordnade och underordnade coroutines.

Lektion 4 av 413 steg

Hur avbrytning sprids i coroutine-hierarkier är en gratis lektion i Kotlin Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Kotlin Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Kotlin Academy innehåller totalt 4 lektioner.

Relationen mellan förälder och barn

När en coroutine startar en annan med launch ansluter sig barnet till förälderns Job. Om föräldern avbryts avbryts alla barn.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val parent = launch {
        launch { delay(1000); println("child 1") }
        launch { delay(1000); println("child 2") }
        delay(1000)
        println("parent")
    }
    delay(50)
    parent.cancel()
    parent.join()
    println("All cancelled")
}

Ett barnfel avbryter föräldern

Om ett barn kastar ett undantag som inte beror på avbrytning avbryter det föräldern och alla syskon — detta är standardbeteendet för Job.

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

Avbrytning propagerar inte uppåt

Att avbryta ett barn avbryter INTE föräldern. Det är bara ohanterade undantag som gör det. En förälder kan när som helst avbryta ett barn.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val parent = launch {
        val child = launch {
            delay(1000)
            println("child done")
        }
        delay(50)
        child.cancel()  // cancels child
        child.join()
        println("parent still running")  // parent is fine
    }
    parent.join()
}

coroutineScope jämfört med GlobalScope

coroutineScope skapar ett underordnat scope: avbrytningar och fel propagerar. GlobalScope skapar föräldralösa coroutines utan förälder — undvik det i produktion.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            launch { delay(50); throw RuntimeException("error") }
        }
    } catch (e: Exception) {
        println("coroutineScope propagated: ${e.message}")
    }
    // GlobalScope.launch { } would NOT propagate to runBlocking
}

Avbryta ett delträd

Varje launch eller async returnerar ett Job. Avbryt ett jobb för att avbryta hela dess delträd, inklusive eventuella kapslade starter.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val root = launch {
        launch {
            launch { delay(1000); println("deep") }
            delay(1000)
        }
    }
    delay(50)
    root.cancel()
    root.join()
    println("Whole subtree cancelled")
}

join() efter cancel()

Anropa alltid join() efter cancel() för att vänta på att coroutinen och dess barn har stoppats helt innan du fortsätter.

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { println("cleanup ran") }
    }
    delay(50)
    job.cancel()
    job.join()  // waits for finally to complete
    println("Proceeded after join")
}

cancelAndJoin()

job.cancelAndJoin() är en bekvämlighetsfunktion som först avbryter och sedan ansluter, vilket motsvarar cancel() + join().

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try { delay(1000) }
        finally { println("cleanup") }
    }
    delay(50)
    job.cancelAndJoin()  // cancel + join in one call
    println("Done")
}

Propagering genom async

Med async lagras undantag i Deferred och kastas när du anropar await(). De propagerar fortfarande till föräldern om de inte hanteras.

import kotlinx.coroutines.*
fun main() = runBlocking {
    try {
        coroutineScope {
            val d = async { throw RuntimeException("async fail") }
            d.await()  // rethrows here
        }
    } catch (e: RuntimeException) {
        println("Caught from async: ${e.message}")
    }
}

Garantin för strukturerad samtidighet

Strukturerad samtidighet garanterar att alla barn har slutförts när ett scope avslutas. Inga coroutines läcker — antingen slutförs de eller så avbryts de.

import kotlinx.coroutines.*
suspend fun doWork() = coroutineScope {
    launch { delay(100); println("work 1") }
    launch { delay(200); println("work 2") }
    // both children complete before doWork returns
}
fun main() = runBlocking {
    doWork()
    println("All work done")
}

Diagram över avbrytningens propagering

Hierarkin: avbrytning av förälder → alla barn avbryts. Avbrytning av barn → endast det delträdet. Undantag i barn → föräldern avbryts → syskon avbryts.

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Parent
    launch {
        val c1 = launch { delay(1000); println("c1") }  // child 1
        val c2 = launch { delay(1000); println("c2") }  // child 2
        delay(50)
        c1.cancel()  // only c1 cancelled
        c1.join()
        println("c2 still active: ${c2.isActive}")
        c2.cancelAndJoin()
    }.join()
}

CoroutineScope-livscykeln i Android

I Android avbryts viewModelScope när ViewModel rensas bort. Alla startade coroutines avbryts automatiskt — ingen manuell rensning behövs.

import kotlinx.coroutines.*
// Pseudocode:
// class MyViewModel : ViewModel() {
//     fun load() = viewModelScope.launch {
//         val data = repo.fetch() // cancelled if VM cleared
//         _state.value = data
//     }
// }
fun main() = runBlocking { println("viewModelScope cancels on ViewModel.onCleared()") }

Snabb kontroll

Vad händer med syskons-coroutines när ett barn kastar ett ohanterat undantag under ett vanligt Job?

Sammanfattning

Avbrytning av föräldern sprids till alla barn. Fel i ett barn propagerar till föräldern och syskonen (med ett vanligt Job). Använd cancelAndJoin() för en ordnad nedstängning. Strukturerad samtidighet säkerställer att inga coroutines läcker.

Gratis att börja

Lär dig Kotlin med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
51
Lektioner
203

Vanliga frågor

Är lektionen ”Hur avbrytning sprids i coroutine-hierarkier” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Kotlin Academy, inklusive ”Hur avbrytning sprids i coroutine-hierarkier”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Kotlin Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Hur avbrytning sprids i coroutine-hierarkier”?

Förstå hur avbrytning sprids genom relationer mellan överordnade och underordnade coroutines. Ni övar på Kotlin Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Kotlin Academy?

Du behöver inga förkunskaper. Utbildningen i Kotlin Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Hur avbrytning sprids i coroutine-hierarkier”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Kotlin Academy-lektionen?

Ja. Varje Kotlin Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Kooperativ avbrytning: isActive och ensureActive
  2. withTimeout och withTimeoutOrNull
  3. Rensa upp med finally och NonCancellable
  4. Hur avbrytning sprids i coroutine-hierarkier
← Tillbaka till Kotlin Academy