Kotlin延迟是否在内部使用调度程序来取消阻塞调用者线程?

时间:2019-03-23 06:07:02

标签: kotlin kotlin-coroutines

这是我用来学习Kotlin协程的一些测试代码。该代码按预期工作,大约需要1秒钟来打印总和,但是现在,如果我用网络请求之类的阻塞调用替换了delay(1000),那么该代码将花费大约10秒钟来打印总和(每次调用大约需要1秒钟)秒),但是如果我将网络调用包装在withContext中并使用IO调度程序,则它需要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 个答案:

答案 0 :(得分:1)

  

延迟功能是否使用某种调度程序来解除线程阻塞?

不仅仅是delay。所有可挂起的功能都与调度程序交互。

您应该问的问题是:“这里由哪个调度员负责?”

答案是:runBlocking安装自己的调度程序,该调度程序将调度到被调用的线程。您代码中的launchasync都会继承它。

请牢记:

  

如果我用网络请求之类的阻塞调用替换delay(1000),则代码将花费大约10秒钟来打印总和(每次调用大约需要1秒钟)

每个阻塞调用将保留在调度程序的单线程上。被阻止时它将无法执行任何其他工作。

  

但是如果我将网络调用包装在withContext中并使用IO调度程序,则打印总和需要1秒钟,因为它是在不同的线程上运行的

是的,这改变了调度程序,问题得以解决。

那么delay的作用是什么?它将挂起当前的协程(async启动的协程),并将控制权返回给调度程序,调度程序现在可以继续以恢复循环并启动下一个协程。