Cancellazione cooperativa: isActive ed ensureActive
Renda cancellabili le coroutine verificando isActive e chiamando ensureActive.
Cancellazione cooperativa: isActive ed ensureActive è una lezione Kotlin Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Kotlin Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Kotlin Academy include 4 lezioni in totale.
Perché la cancellazione cooperativa?
Le coroutine Kotlin utilizzano la cancellazione cooperativa: una coroutine cancellata viene arrestata soltanto quando collabora controllando il proprio stato di cancellazione. Un ciclo CPU intenso non si fermerà finché non eseguirà questo controllo.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
var i = 0
while (true) { i++ } // never checks — never cancels!
}
delay(100)
job.cancel()
println("cancel sent but loop kept running until process ended")
}Controllare isActive
isActive è una proprietà di CoroutineScope che restituisce false quando viene richiesta la cancellazione. Controllarla in un ciclo consente alla coroutine di collaborare.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
var i = 0
while (isActive) {
i++
}
println("Loop exited after $i iterations")
}
delay(10)
job.cancel()
job.join()
}ensureActive()
ensureActive() genera CancellationException se la coroutine è stata cancellata. È un sostituto diretto di if (!isActive) throw CancellationException().
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
repeat(1_000_000) {
ensureActive() // throws if cancelled
// heavy computation here
}
} catch (e: CancellationException) {
println("Cancelled at iteration")
throw e
}
}
delay(5)
job.cancel()
job.join()
}yield() come punto di cooperazione
yield() sospende brevemente la coroutine, consentendo allo scheduler di controllare la cancellazione ed eseguire altre coroutine.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
repeat(10) { i ->
yield() // cooperative cancellation point + gives up scheduler
println("Step $i")
}
}
delay(2)
job.cancel()
job.join()
println("Done")
}isActive e ensureActive
Utilizzi isActive per la logica condizionale, ad esempio per uscire con eleganza da un ciclo. Utilizzi ensureActive() quando desidera propagare immediatamente la cancellazione come eccezione.
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
repeat(100) { i ->
if (!isActive) {
println("Stopping at $i, cleaning up...")
return@launch
}
// work
}
}.also { delay(5); it.cancel(); it.join() }
}CancellationException è speciale
CancellationException non viene propagata al parent: segnala una cancellazione normale. Non la ignori mai; la rilanci sempre oppure lasci che si propaghi.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
delay(1000)
} catch (e: CancellationException) {
println("Caught cancellation, rethrowing")
throw e // important!
}
}
delay(50)
job.cancel()
job.join()
println("Job state: ${job.isCancelled}")
}Cancellazione nelle operazioni vincolate alla CPU
Per le operazioni vincolate alla CPU, inserisca ensureActive() o yield() nei punti di controllo naturali, così da consentire una cancellazione tempestiva.
import kotlinx.coroutines.*
suspend fun heavyCompute(n: Int): Long {
var result = 0L
for (i in 0..n) {
ensureActive()
result += i
}
return result
}
fun main() = runBlocking {
val job = launch(Dispatchers.Default) {
println(heavyCompute(1_000_000))
}
delay(10)
job.cancel()
job.join()
}isActive in una funzione suspend personalizzata
Può accedere a isActive all'interno di qualsiasi funzione suspend tramite coroutineContext.isActive oppure utilizzando currentCoroutineContext().isActive.
import kotlinx.coroutines.*
suspend fun checkable() {
while (currentCoroutineContext().isActive) {
delay(10)
println("tick")
}
}
fun main() = runBlocking {
val job = launch { checkable() }
delay(35)
job.cancel()
job.join()
}Cancellazione con pulizia delle risorse
Anche con la cancellazione cooperativa, le risorse possono essere pulite nei blocchi finally: l'eccezione di cancellazione continua a propagarsi attraverso di essi.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
repeat(100) { i ->
ensureActive()
delay(20)
println("Working $i")
}
} finally {
println("Cleanup done")
}
}
delay(50)
job.cancel()
job.join()
}Polling con isActive
I cicli di polling sono perfetti per isActive: continui a eseguire il polling finché la coroutine non viene cancellata.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
while (isActive) {
println("Polling...")
delay(100)
}
println("Poller stopped")
}
delay(350)
job.cancel()
job.join()
}Differenza rispetto a Thread.interrupted()
A differenza dei thread Java, le coroutine Kotlin non si basano su flag di interruzione. La cancellazione viene modellata tramite eccezioni e lo stato dello scope, il che la rende componibile e strutturata.
import kotlinx.coroutines.*
fun main() = runBlocking {
// Kotlin way: cooperative via isActive / ensureActive
launch {
ensureActive()
println("Kotlin coroutine: cancellation is explicit and structured")
}
}Verifica rapida
Quale funzione genera immediatamente un'eccezione quando una coroutine viene cancellata?
Riepilogo
La cancellazione cooperativa richiede punti di controllo espliciti: isActive per uscire in modo condizionale, ensureActive() per generare immediatamente un'eccezione, yield() per sospendersi e liberare il thread. Non ignori mai CancellationException.
Domande Frequenti
La lezione «Cancellazione cooperativa: isActive ed ensureActive» è gratuita?
Sì — il testo completo di «Cancellazione cooperativa: isActive ed ensureActive» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Kotlin Academy, passa a CoddyKit PRO. Il corso Kotlin Academy include 4 lezioni in totale.
Cosa imparerò in «Cancellazione cooperativa: isActive ed ensureActive»?
Renda cancellabili le coroutine verificando isActive e chiamando ensureActive. Eserciti Kotlin Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Kotlin Academy?
Non è richiesta alcuna esperienza precedente. Kotlin Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Cancellazione cooperativa: isActive ed ensureActive»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Kotlin Academy?
Sì. Ogni lezione Kotlin Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Cancellazione cooperativa: isActive ed ensureActive
- withTimeout e withTimeoutOrNull
- Pulizia con finally e NonCancellable
- Propagazione della cancellazione nelle gerarchie di coroutine