为何Kotlin协程GlobalScope搭配Dispatchers.Main会抛出异常?
问题:使用Dispatchers.Main启动协程抛出RuntimeException,切换至IO/Default调度器可正常运行
问题重现代码
fun main(args: Array<String>) { println(" Program Starts to run") GlobalScope.launch(Dispatchers.Main) { delay(2000) println("Program inside global scope launch") } println(" Program Ends Now") }
抛出的异常
Exception in thread "main" java.lang.RuntimeException: Exception while trying to handle coroutine exception at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
原因分析
Dispatchers.Main是为UI主线程设计的调度器,但在纯JVM运行环境(比如直接执行main函数的场景)下,kotlinx-coroutines-core核心库本身并没有提供它的默认实现。只有引入对应UI平台的协程扩展库(比如Android的kotlinx-coroutines-android、Swing的kotlinx-coroutines-swing)后,Dispatchers.Main才有可用的线程调度逻辑。
而Dispatchers.IO和Dispatchers.Default是kotlinx-coroutines-core自带的调度器,基于JVM线程池实现,无需额外依赖就能正常工作。
另外还有一个潜在问题:即便解决了Main调度器的依赖问题,当前代码的main函数会直接执行完毕退出,协程还没来得及执行就会被终止,你也看不到协程内的打印输出。
解决方案
1. 引入对应平台的Main调度器依赖
如果是Android开发,在build.gradle中添加:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:版本号'
如果是桌面Swing/JavaFX应用,对应添加kotlinx-coroutines-swing或kotlinx-coroutines-javafx依赖,版本号需与kotlinx-coroutines-core保持一致。
2. 阻塞主线程等待协程完成
修改main函数,用runBlocking包裹逻辑,避免主线程提前退出:
fun main(args: Array<String>) { println(" Program Starts to run") runBlocking { launch(Dispatchers.Main) { delay(2000) println("Program inside global scope launch") } } println(" Program Ends Now") }
也可以通过join()方法单独等待目标协程完成:
fun main(args: Array<String>) { println(" Program Starts to run") val job = GlobalScope.launch(Dispatchers.Main) { delay(2000) println("Program inside global scope launch") } runBlocking { job.join() } // 等待协程执行完毕 println(" Program Ends Now") }
3. 避免使用GlobalScope(推荐)
GlobalScope的生命周期不受控制,容易引发内存泄漏,建议使用自定义CoroutineScope:
fun main(args: Array<String>) { println(" Program Starts to run") val mainScope = CoroutineScope(Dispatchers.Main) val job = mainScope.launch { delay(2000) println("Program inside global scope launch") } runBlocking { job.join() } mainScope.cancel() // 手动取消Scope释放资源 println(" Program Ends Now") }
内容的提问来源于stack exchange,提问作者SAMIR R
相关产品推荐
相关产品推荐

