在协程中如果发生了异常,那么这个异常的传播路径是什么样的呢,
先来说一下异常传播时比较好理解传播途径
下面上例子
@JvmStatic
fun main(array: Array<String>) {
runBlocking {
CoroutineScope(Dispatchers.IO).launch {
var job1 = launch {
launch {
launch {
launch {
delay(1000)
}
}
}.join()
println("--------job1 执行完成-----------")
}
var job2 = launch {
launch {
launch {
launch {
launch {
delay(100)
throw ClassCastException("报错了")
}
}
}
}
}
delay(200)
println("------父协程执行完毕-----------")
}
delay(2000)
}
}
结果:
Exception in thread "DefaultDispatcher-worker-2 @coroutine#8" java.lang.ClassCastException: 报错了
at com.tsm.opencv.Tsm$main$1$1$job2$1$1$1$1$1.invokeSuspend(Tsm.kt:29)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:100)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [CoroutineId(2), "coroutine#2":StandaloneCoroutine{Cancelling}@2c66815a, Dispatchers.IO]
Process finished with exit code 0
在这个例子中, runBlocking 作用域中创建了一个 CoroutineScope 并指定了他的新的作用域,那么他就省升级为顶级父协程,同时在 CoroutineScope 作用域中创建了2个 launch 的嵌套子作用域, 在 launch 2 子协程中发生了异常,但是他导致了 launch 1中的没有打印,同时 父协程中的结束也没有打印,
在没有特殊处理的情况下,子协程如果发生了异常,那么这个异常会逐级向上抛出,直到顶级父作用域,顶级作用域接受到异常后,会取消抛出异常协程的兄弟协程
图片中就展示了异常的传播过程,laucn 2先抛出异常,随后沿着红色路线逐级上抛,到达顶级父协程后,再有顶级父协程延颜色路线再逐级向下抛
如果在创建父协程时使用supervisorScope 或者supervisorjob 那么异常传递到顶级父协程后将不会再向下传递