协程:main() runBlocking 与 suspend main
Coroutines: main() runBlocking vs suspend main
取下面两个代码示例(分别取自 Kotlin 文档和协程库 README):
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(2000)
println("World")
}
println("Hello")
}
在 Kotlin >= 1.3.0 中,可以将 main()
函数标记为 suspend
able 并直接使用 coroutineScope
。
import kotlinx.coroutines.*
suspend fun main() = coroutineScope {
launch {
delay(2000)
println("World")
}
println("Hello")
}
两者产生相同的输出:
Hello
World
这两种方法在功能上有什么区别吗?如果是,它们是什么?
runBlocking()
和 coroutineScope()
在功能上非常相似。它们都暂停当前执行,等待内部协程完成。不同之处在于 runBlocking()
是从常规 non-suspendable 代码执行的,因此它通过阻塞等待,而 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()
也使用主线程执行,但它没有指定调度程序,所以每当你使用例如coroutineScope()
它将切换到 Dispatchers.Default
。因此,您的 runBlocking()
示例使用 single-threaded 调度程序,而您的 coroutineScope()
示例使用 multi-threaded Dispatchers.Default
。但是,在两种方法之间进行选择时,实际上不应考虑这种差异。我们可以非常轻松地随时切换调度程序。
取下面两个代码示例(分别取自 Kotlin 文档和协程库 README):
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(2000)
println("World")
}
println("Hello")
}
在 Kotlin >= 1.3.0 中,可以将 main()
函数标记为 suspend
able 并直接使用 coroutineScope
。
import kotlinx.coroutines.*
suspend fun main() = coroutineScope {
launch {
delay(2000)
println("World")
}
println("Hello")
}
两者产生相同的输出:
Hello
World
这两种方法在功能上有什么区别吗?如果是,它们是什么?
runBlocking()
和 coroutineScope()
在功能上非常相似。它们都暂停当前执行,等待内部协程完成。不同之处在于 runBlocking()
是从常规 non-suspendable 代码执行的,因此它通过阻塞等待,而 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()
也使用主线程执行,但它没有指定调度程序,所以每当你使用例如coroutineScope()
它将切换到 Dispatchers.Default
。因此,您的 runBlocking()
示例使用 single-threaded 调度程序,而您的 coroutineScope()
示例使用 multi-threaded Dispatchers.Default
。但是,在两种方法之间进行选择时,实际上不应考虑这种差异。我们可以非常轻松地随时切换调度程序。