← Назад к вопросам

Как происходит прерывание корутин

2.4 Senior🔥 171 комментариев
#Kotlin основы#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Механизм прерывания корутин в Kotlin

Прерывание корутин в Kotlin происходит через механизм отмены (cancellation), который является кооперативным - корутина должна регулярно проверять свой статус и корректно завершать работу при запросе отмены.

Основные принципы отмены

Job - ключевой интерфейс, представляющий корутину. Каждая корутина связана с Job, который управляет её жизненным циклом:

val job = CoroutineScope(Dispatchers.Default).launch {
    // Работа корутины
}

Как инициировать прерывание

// 1. Отмена конкретной корутины
job.cancel()

// 2. Отмена всех корутин в скоупе
scope.cancel()

// 3. Отмена с причиной
job.cancel("Причина отмены", CancellationException())

Кооперативная проверка отмены

Корутина должна явно проверять статус отмены:

suspend fun doWork() {
    val job = launch {
        for (i in 1..1000) {
            // Проверяем, не отменена ли корутина
            ensureActive()
            // Или альтернативная проверка
            if (!isActive) {
                throw CancellationException()
            }
            // Долгая операция
            delay(100)
        }
    }
    
    delay(500) // Ждём полсекунды
    job.cancel() // Инициируем отмену
}

Автоматическая отмена в suspend функциях

Большинство стандартных suspend функций (delay(), yield(), withContext() и др.) автоматически проверяют отмену:

suspend fun processItems(items: List<Int>) {
    items.forEach { item ->
        delay(100) // delay() автоматически проверяет cancel()
        // Если корутина отменена, delay() выбросит CancellationException
        processItem(item)
    }
}

Обработка исключений отмены

CancellationException - специальный тип исключения, который НЕ ловится обычными блоками try-catch:

val job = launch {
    try {
        repeat(1000) { i ->
            println("Job: I'm sleeping $i ...")
            delay(500)
        }
    } catch (e: CancellationException) {
        // Обрабатываем отмену
        println("Job: I was cancelled")
        throw e // Важно: пробрасываем исключение дальше
    } finally {
        // Блок finally выполняется даже при отмене
        println("Job: I'm running finally")
    }
}

Отмена с таймаутом

// Автоматическая отмена после таймаута
withTimeout(1300) {
    repeat(1000) { i ->
        println("I'm sleeping $i ...")
        delay(500)
    }
}

// Или с обработкой таймаута
val result = withTimeoutOrNull(1300) {
    repeat(1000) { i ->
        println("I'm sleeping $i ...")
        delay(500)
    }
    "Done" // Вернётся, если уложились в таймаут
}

Важные особенности:

  1. Кооперативность: Корутина не прерывается мгновенно. Она должна сотрудничать, проверяя флаг отмены.
  2. Нераспространяемость: CancellationException не прокидывается в родительскую корутину.
  3. Невозобновляемость: После отмены Job нельзя перезапустить.
  4. Иерархическая отмена: При отмене родительской Job отменяются все дочерние.

Пример комплексной отмены:

suspend fun complexOperation(): String = coroutineScope {
    val job1 = async { fetchDataFromSource1() }
    val job2 = async { fetchDataFromSource2() }
    
    try {
        val result1 = job1.await()
        val result2 = job2.await()
        combineResults(result1, result2)
    } finally {
        // Очистка ресурсов при отмене
        if (isCancelled) {
            cleanupResources()
        }
    }
}

// Вызов с таймаутом
try {
    val result = withTimeout(5000) {
        complexOperation()
    }
} catch (e: TimeoutCancellationException) {
    println("Operation timed out")
}

Рекомендации по работе с отменой:

  • Всегда проверяйте isActive в долгих вычислительных циклах
  • Используйте ensureActive() для удобной проверки
  • Освобождайте ресурсы в блоке finally
  • Избегайте блокирующих операций без проверки отмены
  • Используйте yield() в CPU-интенсивных задачах для проверки отмены

Правильная обработка отмены делает корутины более надёжными и предотвращает утечки ресурсов при досрочном завершении операций.