Kotlin 未处理的协程异常不会崩溃

Nub*_*ase 4 kotlin kotlin-coroutines

我预计以下程序会崩溃,但事实并非如此。它只是打印线程发生异常并正常退出。为什么?

import kotlinx.coroutines.*

fun main() {
    val scope = CoroutineScope(Dispatchers.Default)
    
    scope.launch {
        delay(100)
        throw RuntimeException("1")
    }
    
    println("sleep")
    Thread.sleep(1000)
    println("exit without crash")
}
Run Code Online (Sandbox Code Playgroud)

操场

Jof*_*rey 6

由于您正在创建自己的CoroutineScope,因此您拥有自己的顶级协程,该协程不绑定到主线程。CoroutineScope手动创建也意味着手动清理(否则您会遇到相同的陷阱,并且GlobalScope可能会泄漏协程或丢失错误)。

只有主线程崩溃了,主程序才会崩溃,这里主线程不会崩溃。如果你想在这个主线程和启动的协程之间建立联系(并传播异常),你应该从一开始就使用结构化并发。

例如,runBlocking在函数顶部使用main()会创建一个CoroutineScope(可用作this),它充当所有启动的协程的父级。它还会在等待所有子协程时阻塞主线程,并传播异常。那么你不需要自己的范围:

fun main() {
    runBlocking(Dispatchers.Default) { // using Dispatchers.Default to be equivalent with your code
    
        launch { // using "this" CoroutineScope from runBlocking
            delay(100)
            throw RuntimeException("1")
        }
    
        println("sleep")
        delay(1000) // using delay instead of Thread.sleep because we're in a coroutine now
        println("exit without crash")
    }
}
Run Code Online (Sandbox Code Playgroud)

这样你就得到:

sleep
Exception in thread "main" java.lang.RuntimeException: 1
 at FileKt$main$1$1.invokeSuspend (File.kt:16) 
 at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33) 
 at kotlinx.coroutines.DispatchedTask.run (DispatchedTask.kt:106) 
Run Code Online (Sandbox Code Playgroud)