Что такое Корутины в Котлине?

Что такое Корутины в Котлине?

Корутины — это отличный функционал, доступный в языке Kotlin. Я уже опробовал его и мне он очень понравился.

Цель этой статьи — помочь вам понять Корутины. Просто будьте внимательны при прочтении и у вас всё получится.

Начнем с официального определения Корутин.

Корутины — это новый способ написания асинхронного, неблокирующего кода.

Первый вопрос, возникающий при прочтении этого определения — чем Корутины отличаются от потоков?

Корутины — это облегчённые потоки. Облегчённый поток означает, что он не привязан к нативному потоку, поэтому он не требует переключения контекста на процессор, поэтому он быстрее.

Что это значит, «не привязан к нативному потоку»?

Корутины есть во многих языках программирования.

В принципе, есть два типа Корутин:

  • использующие стек;
  • неиспользующиие стек;

Kotlin реализует Корутины без стека — это значит, что в Корутинах нет собственного стека, поэтому они не привязываются к нативному потоку.

И Корутины, и потоки являются многозадачными. Но разница в том, что потоки управляются ОС, а Корутины пользователями.

Теперь вы можете осознанно прочитать и понять выдержку с официального сайта Kotlin:

Корутины можно представить в виде облегчённого потока. Подобно потокам, корутины могут работать параллельно, ждать друг друга и общаться. Самое большое различие заключается в том, что корутины очень дешевые, почти бесплатные: мы можем создавать их тысячами и платить очень мало с точки зрения производительности. Потоки же обходятся дорого. Тысяча потоков может стать серьезной проблемой даже для современной машины.

Давайте посмотрим, как работать с Корутинами

Итак, как запустить корутину (по аналогии с запуском потока)?

Есть две функции для запуска корутины:

  • launch{}
  • async{}

launch{} vs async{} в Корутинах Kotlin

Разница в том, что launch{} ничего не возвращает, а async{} возвращает экземпляр Deferred, в котором имеется функция await(), которая возвращает результат корутины, прямо как Future в Java, где мы делаем future.get() для получения результата.

###Давайте посмотрим на использование launch{}

fun main(args: Array<String>) {
    println("Kotlin Start")
    launch(CommonPool) {
        delay(2000)
        println("Kotlin Inside")
    }
    println("Kotlin End")
}
// The output will be
// Kotlin Start
// Kotlin End
// Kotlin Inside

Этот код запустит новую корутину в данном пуле потоков. В этом случае мы используем CommonPool, который использует ForkJoinPool.commonPool(). Потоки все ещё существуют в программе, основанной на корутинах, но один поток может запускать много корутин, поэтому нет необходимости в слишком большом количестве потоков.

Попробуем одну вещь:

fun main(args: Array<String>) {
    delay(2000)
}

Если вы cделаете это прямо в основной функции, то получите сообщение об ошибке:

Функции прерывания можно вызвать только из корутины или другой функции прерывания.

Функция задержки является функцией прерывания, соответственно мы можем ее вызывать только из корутины или другой функции прерывания.

Давайте исправим это:

fun main(args: Array<String>) {
    runBlocking {
        delay(2000)
    }
}

Ещё один пример:

suspend fun doWorkFor1Seconds(): String {
    delay(1000)
    return "doWorkFor1Seconds"
}
suspend fun doWorkFor2Seconds(): String {
    delay(2000)
    return "doWorkFor2Seconds"
}
// Serial execution 
private fun doWorksInSeries() {
    launch(CommonPool) {
        val one = doWorkFor1Seconds()
        val two = doWorkFor2Seconds()
        println("Kotlin One : " + one)
        println("Kotlin Two : " + two)
    }
}
// The output is
// Kotlin One : doWorkFor1Seconds
// Kotlin Two : doWorkFor2Seconds

Теперь посмотрим на использование async{}

// Parallel execution
private fun doWorksInParallel() {
    val one = async(CommonPool) {
        doWorkFor1Seconds()
    }
    val two = async(CommonPool) {
        doWorkFor2Seconds()
    }
    launch(CommonPool) {
        val combined = one.await() + "_" + two.await()
        println("Kotlin Combined : " + combined)
    }
}
// The output is
// Kotlin Combined : doWorkFor1Seconds_doWorkFor2Seconds

Т.к. мы используем async{}, то можем вызвать await() для получения результата.

Счастливого обучения ;)

Перевод статьи «What are Coroutines in Kotlin?»

ПОХОЖИЕ ПУБЛИКАЦИИ

2283
10/07/2018

0 комментариев к статье "Что такое Корутины в Котлине?"

Добавить комментарий