Kotlin启动与启动(调度程序,默认)

but5z9lq  于 2022-11-16  发布在  Kotlin
关注(0)|答案(1)|浏览(191)

我测试了阻塞代码和协程是如何交互的,以便于我自己理解。显然,我们应该使用非阻塞代码,但我想了解如果有一些阻塞代码在那里会发生什么。
如果我运行以下命令:

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,如果没有指定的话?),launch块将在一个单独的协程中运行并立即启动。
那么,为什么launch(Dispatchers.Default)允许第二个协程启动,而launch不允许呢?

ruarlubt

ruarlubt1#

我以为启动使用了Dispatchers。如果您没有指定一个,默认情况下是默认的
这就是您的错误之处。下面是documentation
协程上下文是从CoroutineScope继承的。可以使用context参数指定其他上下文元素。如果上下文没有任何调度程序或任何其他ContinuationInterceptor,则使用Dispatchers.Default。
这意味着如果你没有给launch传递一个调度器,它将默认为launch的上下文中的调度器,如果协程上下文没有调度器,* 那么 * launch将使用Dispatchers.Default
因此,在您的示例中,无参数的launch继承了上下文,从而继承了runBlocking提供的调度程序,runBlocking是一个单线程调度程序,运行在它阻塞的线程(这里是主线程)上。
为什么launch(Dispatchers.Default)允许第二个协程启动,而launch不允许呢?
这是因为,正如我们刚刚看到的,这两种情况并不涉及相同的线程。对于launch(Dispatchers.Default),启动的协程运行在一个单独的线程池中,并且可以与主线程池并行运行。然而,对于无参数的launch,第二个协程与代码的其余部分运行在同一个线程中,因为它运行在runBlocking的单线程调度器中。其由主线程支持。
最后一块拼图是Thread.sleep是 * 阻塞 *(正如您所说的),不像delay,它是协程库中的挂起等价物。(在无参数launch的情况下),运行最后一个Thread.sleep会阻塞主线程,并且永远不会给其他协程运行的机会。您需要一些东西来挂起执行,例如delay()

相关问题