Sobes.tech
Middle

Какво е корутина в Kotlin и как работи?

sobes.tech AI

Отговор от AI

Корутина в Kotlin — това е лека единица за изпълнение, която позволява да се пише асинхронен неблокиращ код по-четлив и последователен начин. Тя е подобна на нишка (thread), но е много по-лека и може лесно да бъде създадена в голямо количество.

Основни компоненти и принципи на работа:

  • Suspend Functions (Suspendable Functions): Функции, маркирани с ключовата дума suspend, могат да спират (suspend) изпълнението си, без да блокират нишката, в която се изпълняват. Когато спряна функция завърши своята "очакваща" операция (например мрежов заявка), тя може да възобнови изпълнението от мястото, където е била спряна.
  • Context (Coroutine context): Комплект от елементи, управляващи поведението на корутината. В контекста влизат:
    • Job: Дескриптор на корутината, който позволява управление на нейния жизнен цикъл (отмяна, изчакване за завършване).
    • CoroutineDispatcher: Определя нишката(ите), в които ще се изпълнява корутината. Позволява превключване между нишки.
    • CoroutineName: Опционално име за отстраняване на грешки.
    • CoroutineExceptionHandler: Обработчик на необработени изключения.
  • Builders (Построители): Функции, които стартират изпълнението на корутини:
    • launch: Стартира нова корутина, без да връща резултат. Връща Job.
    • async: Стартира нова корутина, която връща резултат (Deferred). За получаване на резултата се използва .await().
    • runBlocking: Блокиращ строител, използван предимно за тестове или интеграция с блокиращ код.

Как работи това под капака:

Корутините не създават отделни нишки за всяка задача. Вместо това, при спиране на suspend функция, компилаторът генерира код, който запазва текущото състояние на изчисленията. Когато резултатът е наличен, корутината се възобновява на една от нишките, управлявани от CoroutineDispatcher. Това се постига чрез преобразуване на suspend функциите в асинхронни извиквания с продължения (continuation-passing style), което позволява на една нишка да изпълнява множество корутини, превключвайки между тях при спиране.

Пример:

import kotlinx.coroutines.*

fun main() = runBlocking { // Блокира текущата нишка до завършване на корутината вътре в runBlocking
    println("Първо")

    launch { // Стартираме нова корутина във фонов режим
        delay(1000L) // Неблокираща забавяне за 1 секунда
        println("След забавянето")
    }

    println("После") // Тази линия ще се изпълни преди завършването на launch корутината
}

Изходът от този код ще бъде:

Първо
После
След забавянето

Това демонстрира неблокиращия характер на launch и delay.