0Pricing
Kotlin Academy · Lekcja

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

  1. Kooperatywne anulowanie: isActive i ensureActive
  2. withTimeout i withTimeoutOrNull
  3. Sprzątanie za pomocą finally i NonCancellable
  4. Propagacja anulowania w hierarchiach korutyn
← Powrót do Kotlin Academy