Использует ли Kotlin delay внутренний диспетчер для разблокировки потока вызывающей стороны? - PullRequest
1 голос
/ 23 марта 2019

Это тестовый код, который я использую для изучения сопрограмм kotlin.Код работает, как ожидалось, и занимает около 1 секунды, чтобы напечатать сумму, но теперь, если я заменяю delay (1000) на блокирующий вызов, такой как сетевой запрос, то для печати суммы требуется около 10 секунд (каждый вызов занимает около 1во-вторых), но если я заверну сетевой вызов в withContext и использую диспетчер ввода-вывода, то для печати суммы потребуется 1 секунда, поскольку она выполняется в другом потоке.Использует ли функция задержки какой-то диспетчер для разблокировки потока?


suspend fun asyncDoubleFn(num: Int): Int {
    delay(1000)
    return num * 2
}


fun main() = runBlocking {
    launch {
        val tt = measureTimeMillis {
            val results = mutableListOf<Deferred<Int>>()
            for (num in 0..10) {
                val result = async { asyncDoubleFn(num + 1) }
                results.add(result)
            }
            val sum = results.map { it.await() }.reduce { acc, i -> acc + i }
            println("[SUM]: $sum")
        }

        println("[TT]: $tt")
    }


    launch {
        println("Another coroutine")
    }

    println("Main Code")


}

1 Ответ

1 голос
/ 24 марта 2019

Использует ли функция задержки какой-либо диспетчер для разблокировки потока?

Не просто delay. Все приостановленные функции взаимодействуют с диспетчером.

Вопрос, который вы должны задать: «Какой диспетчер здесь отвечает?»

И ответ таков: runBlocking устанавливает свой собственный диспетчер, который отправляет поток, в который он вызван. И launch, и async в вашем коде наследуют его.

Имея это в виду:

Если я заменю задержку (1000) на блокирующий вызов, такой как сетевой запрос, то для вывода суммы на код потребуется около 10 секунд (каждый вызов занимает около 1 секунды)

Каждый блокирующий вызов будет удерживаться в одном потоке диспетчера. Он не сможет выполнять какую-либо другую работу, будучи заблокированным.

но если я заверну сетевой вызов в withContext и использую диспетчер IO, то для печати суммы потребуется 1 секунда, поскольку он выполняется в другом потоке

Да, это меняет диспетчера, проблема решена.

Итак, что делает delay? Он приостанавливает текущую сопрограмму (запущенную async) и возвращает управление диспетчеру, который теперь может возобновить цикл и запустить следующую сопрограмму.

...