协程:main() runBlocking 与 suspend main

xcu*_*pir 11 kotlin kotlin-coroutines

获取以下两个代码示例(分别取自 Kotlin 文档和协程库 README):

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(2000)
        println("World")
    }
    println("Hello")
}
Run Code Online (Sandbox Code Playgroud)

在 Kotlin >= 1.3.0 中,可以将main()函数标记为suspend能够并直接使用 a coroutineScope

import kotlinx.coroutines.*

suspend fun main() = coroutineScope {
    launch {
        delay(2000)
        println("World")
    }
    println("Hello")
}
Run Code Online (Sandbox Code Playgroud)

两者产生相同的输出:

Hello
World
Run Code Online (Sandbox Code Playgroud)

这两种方法之间有功能差异吗?如果有,它们是什么?

bro*_*oot 18

runBlocking()并且coroutineScope()在功能上非常相似。它们都暂停当前的执行,等待内部协程完成。不同之处在于,runBlocking()它是从常规的不可挂起的代码中执行的,因此它通过阻塞等待,并coroutineScope()从可挂起的上下文中使用,因此它挂起。

这种差异使得他们在内部做很多不同的事情。runBlocking()必须首先初始化整个协程机制,然后才能执行可挂起的 lambda。coroutineScope()可以访问现有的协程上下文,因此它只安排内部 lambda 执行并挂起。

现在,suspend fun main()它只是 Kotlin 编译器提供的一个“快捷方式”,以便更轻松地初始化协程应用程序。在内部,它在真正的主函数和可挂起的主函数之间建立了一座桥梁。它生成一个单独的main()函数,该函数不可挂起,并且是“真正的”主函数。该函数初始化一个协程并使用内部runSuspend()实用程序来执行您的suspend fun main(). 此处描述: https: //github.com/Kotlin/KEEP/blob/master/proposals/enhancing-main-convention.md#implementation-details-on-jvm-1

两种启动协程应用程序的方法非常相似,您可以根据自己的喜好进行选择。一个显着的区别是runBlocking()使用当前的“主”线程创建调度程序。suspend fun main()也使用主线程执行,但它没有指定调度程序,因此每当您使用eg时,coroutineScope()它都会切换到Dispatchers.Default. 因此,您的runBlocking()示例使用单线程调度程序,而您的coroutineScope()示例使用多线程Dispatchers.Default。然而,在这两种方法之间进行选择时,不应真正考虑这种差异。我们可以随时轻松切换调度员。