Kooperatywne anulowanie: isActive i ensureActive
Spraw, aby korutyny można było anulować, sprawdzając isActive i wywołując ensureActive.
Kooperatywne anulowanie: isActive i ensureActive to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Dlaczego anulowanie kooperatywne?
Korutyny Kotlin używają kooperatywnego anulowania: anulowana korutyna zostaje zatrzymana dopiero wtedy, gdy współpracuje, sprawdzając swój stan anulowania. Pętla intensywnie obciążająca procesor nie zatrzyma się, dopóki nie wykona takiego sprawdzenia.
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")
}Sprawdzanie isActive
isActive to właściwość obiektu CoroutineScope, która zwraca false, gdy tylko zostanie zgłoszone żądanie anulowania. Sprawdzanie jej w pętli pozwala korutynie współpracować przy anulowaniu.
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() zgłasza CancellationException, jeśli korutyna została anulowana. Jest bezpośrednim zamiennikiem konstrukcji 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() jako punkt współpracy
yield() na krótko zawiesza korutynę, umożliwiając harmonogramowi sprawdzenie anulowania i uruchomienie innych korutyn.
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 a ensureActive
Użyj isActive w logice warunkowej (na przykład, aby łagodnie wyjść z pętli). Użyj ensureActive(), gdy chcesz natychmiast przekazać anulowanie jako wyjątek.
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 jest szczególnym wyjątkiem
CancellationException nie jest propagowany do rodzica — sygnalizuje normalne anulowanie. Nigdy go nie przechwytuj bez obsługi; zawsze rzuć go ponownie albo pozwól mu się propagować.
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}")
}Anulowanie pracy obciążającej CPU
W przypadku pracy obciążającej CPU należy umieszczać ensureActive() lub yield() w naturalnych punktach kontrolnych, aby umożliwić szybkie anulowanie.
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 w niestandardowej funkcji zawieszającej
Do właściwości isActive można uzyskać dostęp w dowolnej funkcji zawieszającej za pomocą coroutineContext.isActive albo 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()
}Anulowanie i zwalnianie zasobów
Nawet przy kooperacyjnym anulowaniu zasoby można zwalniać w blokach finally — wyjątek anulowania nadal propaguje się przez te bloki.
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()
}Odpytywanie za pomocą isActive
Pętle odpytywania doskonale nadają się do użycia z isActive: należy odpytywać tak długo, aż korutyna zostanie anulowana.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
while (isActive) {
println("Polling...")
delay(100)
}
println("Poller stopped")
}
delay(350)
job.cancel()
job.join()
}Różnica względem Thread.interrupted()
W przeciwieństwie do wątków Java, korutyny Kotlin nie korzystają z flag przerwania. Anulowanie jest modelowane za pomocą wyjątków i stanu zakresu, dzięki czemu można je komponować oraz stosować w sposób ustrukturyzowany.
import kotlinx.coroutines.*
fun main() = runBlocking {
// Kotlin way: cooperative via isActive / ensureActive
launch {
ensureActive()
println("Kotlin coroutine: cancellation is explicit and structured")
}
}Szybkie sprawdzenie
Która funkcja natychmiast zgłasza wyjątek po anulowaniu korutyny?
Podsumowanie
Kooperacyjne anulowanie wymaga jawnych punktów kontrolnych: isActive służy do warunkowego zakończenia, ensureActive() natychmiast zgłasza wyjątek, a yield() zawiesza korutynę i zwalnia wątek. Nigdy nie ignoruj CancellationException.
Często zadawane pytania
Czy lekcja „Kooperatywne anulowanie: isActive i ensureActive” jest bezpłatna?
Tak — pełny tekst „Kooperatywne anulowanie: isActive i ensureActive” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Kooperatywne anulowanie: isActive i ensureActive”?
Spraw, aby korutyny można było anulować, sprawdzając isActive i wywołując ensureActive. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?
Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Kooperatywne anulowanie: isActive i ensureActive”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?
Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Kooperatywne anulowanie: isActive i ensureActive
- withTimeout i withTimeoutOrNull
- Sprzątanie za pomocą finally i NonCancellable
- Propagacja anulowania w hierarchiach korutyn