为何Kotlin协程添加delay(200ms)后仍先输出A再输出B?
Kotlin协程添加延迟后输出顺序疑问
以下两段代码运行在Kotlin Playground环境中:
代码片段1
fun main() { CoroutineScope(Dispatchers.IO).launch { print("A") } print("B") }
输出:AB
代码片段2
fun main() { CoroutineScope(Dispatchers.IO).launch { delay(200) print("A") } print("B") }
用户观察到输出仍为AB,疑惑为何添加200ms延迟后A仍先于B打印。
原因解释
首先得明确:标准JVM环境下的行为和你在Playground看到的完全不同:
- 代码片段1:
main函数的print("B")和协程的print("A")执行顺序完全不确定,可能输出AB也可能是BA;而且main执行完后JVM会直接退出,如果协程还没来得及执行,A根本不会被打印。 - 代码片段2:
main会先执行print("B"),随后JVM立刻退出,协程因为挂起且没有被等待,A根本不会执行。
你在Playground看到的现象,是平台特殊处理导致的:
- 强制等待协程完成:Playground为了让用户看到协程的执行结果,会在
main函数结束后等待所有后台协程跑完才终止程序,所以哪怕协程里有delay(200),A最终还是会被打印。 - 偶发的输出顺序异常:你看到的
AB顺序是极端偶发的线程调度巧合,或者输出缓冲的显示问题。正常情况下,这段代码在Playground里应该先输出B,等200ms后再输出A,最终显示BA。
为什么会出现这种偶发情况?因为线程调度没有绝对的先后顺序:
- 调用
launch后,协程被提交到Dispatchers.IO线程池,但delay(200)会让协程挂起、释放线程,进入等待状态。 - 主线程此时本该立刻执行
print("B"),但如果Playground的主线程因环境负载等原因被短暂阻塞,刚好协程在delay结束后先完成了print("A"),就会出现AB的输出顺序。但这不是常态,多运行几次大概率会看到BA。
最后提醒:实际开发中别用这种自定义的CoroutineScope,应该用runBlocking、viewModelScope这类带生命周期管理的作用域,避免协程泄漏或执行时机不可控的问题。
内容的提问来源于stack exchange,提问作者Neo Wakeup
相关产品推荐
相关产品推荐

