You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询:GlobalScope.launch在runBlocking主函数中未完成任务的原因

为什么GlobalScope.launch里的任务没完成?

嘿,这个问题的核心原因其实是程序过早退出,和GlobalScope的特性直接挂钩:

  • runBlocking只会等待它自己作用域内的协程执行完毕,但GlobalScope.launch创建的是全局作用域的独立协程,完全不受runBlocking的管控。
  • 你的main函数里,runBlocking代码块只做了一件事:启动GlobalScope的协程,之后就没有其他代码了。这意味着runBlocking会立刻结束,整个JVM进程随即退出——此时GlobalScope里的协程还没来得及跑完那10次循环(每次还要等100ms),文件写入操作自然就没机会完成,最后就得到了空文件。

你可以做个小测试验证这个逻辑:在runBlocking代码块的最后加一行delay(2000),你会发现文件能正常写入内容,因为这时候程序没有立刻退出,给了GlobalScope协程足够的执行时间。但这显然不是正经的解决办法。

正确的解决方案有两种:

1. 抛弃GlobalScope,使用runBlocking的作用域启动协程

这是最推荐的方式,因为这样协程会被runBlocking管辖,runBlocking会自动等待它完成:

fun main() = runBlocking<Unit> {
    launch { // 直接使用runBlocking的作用域,无需GlobalScope
        val file = File(javaClass.getResource("/coroutines_file.txt").path)
        file.printWriter().use { out ->
            repeat(10) { i ->
                delay(100)
                out.println(i.toString())
            }
        }
    }
}

2. 手动等待GlobalScope的协程完成(不推荐)

如果因为某些原因非要用GlobalScope,你可以把协程的Job对象保存下来,调用join()让runBlocking等待它执行完毕:

fun main() = runBlocking<Unit> {
    val job = GlobalScope.launch {
        val file = File(javaClass.getResource("/coroutines_file.txt").path)
        file.printWriter().use { out ->
            repeat(10) { i ->
                delay(100)
                out.println(i.toString())
            }
        }
    }
    job.join() // 手动等待全局协程完成
}

最后再提一句:

GlobalScope之所以不被推荐,就是因为它的协程脱离了任何作用域的管控,很容易出现这种“任务没跑完程序就结束”的问题,甚至会导致协程泄露。日常开发中尽量使用带明确生命周期的协程作用域,比如自定义CoroutineScope等。

内容的提问来源于stack exchange,提问作者HaKIM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:45:39