为什么 Kotlin 协程即使有延迟也会输出“A B”?

Neo*_*eup 4 kotlin kotlin-coroutines

我有以下使用协程的 Kotlin 代码片段,我对输出感到困惑。有人可以解释为什么在这两种情况下输出都是“A B”吗?

// Code Snippet 1
fun main() {
  CoroutineScope(Dispatchers.IO).launch { 
        print("A")
    }
    print("B")
}
Run Code Online (Sandbox Code Playgroud)

输出:AB

// Code Snippet 2
fun main() {
    CoroutineScope(Dispatchers.IO).launch { 
        delay(200)
        print("A")
    }
    print("B")
}
Run Code Online (Sandbox Code Playgroud)

输出AB

我已经在 kotlin 游乐场上运行了这段代码(链接 - kotlin 游乐场 我无法理解为什么 A 在 B 之前打印,即使添加了 200ms 的延迟

Jof*_*rey 6

有趣的。我预计至少第二种情况只能 print B,因为程序在A有机会打印之前终止。这实际上是我在 IDE 中运行代码时得到的结果。

您的游乐场链接使用println,而不是print,但A B在同一行上打印这个奇怪的输出。从不同线程输出时,这可能是 Kotlin 游乐场的标准输出处理中的错误。我想不要相信来自游乐场的并发输出。

编辑:我确认,游乐场收到的有效负载包含"text": "A\n<outStream>B\n</outStream>",这似乎解释了并发输出的错误显示(只有主线程的输出包含在<outStream>此处)。

除了这个错误之外,您应该注意,您不会在这里等待以任何方式启动的协程。这意味着任何执行顺序在技术上都是可能的:主体可以在启动的协程执行之前或之后打印 B,并且程序甚至可以在启动的协程执行或完成之前终止。

您可以在最后使用Thread.sleep()来阻止主线程,同时等待其他协程完成,但这对于协程来说不是惯用的。

如果你想自动等待协程完成,你应该使用结构化并发(例如这里使用 arunBlocking或 a suspend fun main()+ coroutineScope):

fun main(): Unit = runBlocking {
    launch(Dispatchers.IO) {
        delay(200)
        println("A")
    }
    println("B")
}
Run Code Online (Sandbox Code Playgroud)

runBlocking在返回之前会自动等待子协程完成,因此您的主线程将被阻塞等待A打印,这将防止程序过早终止。