为了我自己的理解,我正在测试阻塞代码和协程如何交互。显然,我们应该使用非阻塞,但我想了解如果其中有一些阻塞代码会发生什么。
如果我运行以下命令:
fun main() {
println("Start: ${Thread.currentThread()}")
runBlocking {
println("Run Blocking : ${Thread.currentThread()}")
launch(Dispatchers.D) { // Immediately scheduled for execution
println("Inside launch: ${Thread.currentThread()}")
}
Thread.sleep(10000)
println("Going to do some other stuff now")
}
println("Out of runBlocking")
}
一切都在同一个协程中运行,并且 Inside launch:
在 Thread.sleep
完成之前不会出现。我认为这是因为它是阻塞的,所以不会发生挂起或使用另一个协程。
如果我将 Dispatchers.Default
传递给 launch
(我认为 launch 默认使用 Dispatchers.Default
,如果你没有指定的话?),启动 block 在单独的协程中运行并立即启动。
那么,为什么 launch(Dispatchers.Default)
允许第二个协程启动,为什么不直接 launch
呢?
最佳答案
I thought launch used Dispatchers.Default by default, if you didn't specify one
这是你弄错的地方。这是 documentation :
The coroutine context is inherited from a CoroutineScope. Additional context elements can be specified with context argument. If the context does not have any dispatcher nor any other ContinuationInterceptor, then Dispatchers.Default is used.
这意味着如果您不将调度程序传递给 launch
,它将默认为您启动 CoroutineScope
上下文中存在的调度程序 启动
。如果协程上下文没有调度程序,then launch
将使用 Dispatchers.Default
。
因此,在您的情况下,无参数 launch
继承了上下文,因此继承了 runBlocking
提供的调度程序,这是一个在它阻塞的线程上运行的单线程调度程序(这里是主线程)。
why does
launch(Dispatchers.Default)
allow the second coroutine to start and why doesn't justlaunch
?
这是因为,正如我们刚刚看到的,这两种情况不涉及相同的线程。使用 launch(Dispatchers.Default)
,启动的协程在单独的线程池上运行,并且可以与主协程并行运行。但是,使用无参数launch
,第二个协程与其余代码运行在同一个线程上,因为它运行在runBlocking
的单线程调度程序中,即由主线程支持。
最后一 block 拼图是 Thread.sleep
是阻塞(如您所说),与 delay
不同,delay
是挂起的等价物来自协程库。当只涉及一个线程时(在无参数 launch
的情况下),运行最后一个 Thread.sleep
会阻塞主线程并且永远不会给其他协程机会运行。您需要一些东西来暂停执行,例如 delay()
。
关于Kotlin 启动与启动(Dispatchers.Default),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74327119/