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

За счет чего корутину можно приостанавливать

3.0 Senior🔥 201 комментариев
#JVM и память#Kotlin основы#Многопоточность и асинхронность

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Приостановка корутин через Continuation

Корутины в Kotlin могут приостанавливаться благодаря Continuation — объекту, который хранит состояние выполнения и может быть возобновлено позже.

Основной механизм

Continuation — это сохранённое состояние программы в точке приостановки. Компилятор преобразует suspend функции в state machine с отдельным состоянием для каждой suspend точки.

suspend fun getUserData(): User = suspendCancellableCoroutine { continuation ->
    api.getUser() { result ->
        continuation.resume(result)
    }
}

Преобразование в State Machine

Когда вы пишете несколько suspend точек, компилятор создаёт state machine, где каждое состояние соответствует участку кода между приостановками.

Диспетчеры и переключение потоков

Корутина может приостанавливаться на одном потоке и возобновляться на другом благодаря ContinuationInterceptor. Dispatcher'ы (Main, IO, Default) реализуют этот интерфейс:

launch(Dispatchers.Main) {
    val user = withContext(Dispatchers.IO) {
        repository.getUser()
    }
    updateUI(user)
}

suspendCancellableCoroutine

Это низкоуровневый API для интеграции callback-based кода с корутинами:

suspend fun getUser(): User = suspendCancellableCoroutine { continuation ->
    api.getUser { result ->
        continuation.resume(result)
    }
}

Ключевые компоненты

  1. Continuation — хранит состояние выполнения программы
  2. State Machine — преобразование suspend функций компилятором
  3. ContinuationInterceptor — управление потоком через Dispatcher'ы
  4. suspend ключевое слово — маркер функции, которая может быть приостановлена
  5. viewModelScope — автоматическая отмена при уничтожении

Практический пример

class UserViewModel : ViewModel() {
    fun loadUser() {
        viewModelScope.launch(Dispatchers.Main) {
            val user = withContext(Dispatchers.IO) {
                api.getUser()
            }
            _userData.value = user
        }
    }
}

Почему это работает

Корутины эффективны потому, что не блокируют потоки. Вместо этого они сохраняют состояние (Continuation), освобождают поток, и возобновляют работу когда результат готов. Это позволяет одному потоку обрабатывать множество корутин без Context Switch затрат, присущих обычным потокам.

На собеседовании

Представьте концепцию как: suspension = сохранение состояния + освобождение потока + возобновление позже с результатом. Это не блокировка, это эффективное управление ресурсами.