父协程遇异常后子协程未取消?SupervisorJob作用解析
协程作用域异常行为疑问解答
为什么测试代码里子协程抛CancellationException后,其他子协程还能执行?
核心原因是**CancellationException在Kotlin协程中属于「正常取消信号」,而非异常失败**:
- 当协程抛出
CancellationException时,只会终止当前协程本身,不会向上传播导致父协程或兄弟协程被取消。 - 看测试代码的结构:外层
scope.launch启动的协程并没有被取消,它在延迟4秒后依然能正常启动第二个子协程,所以会输出child 2 coroutine。 - 只有当子协程抛出非
CancellationException类型的异常时,才会触发普通Job作用域的连锁取消逻辑——父协程被取消,所有兄弟子协程也跟着终止。
使用CoroutineScope(Dispatchers.IO + SupervisorJob())的区别
普通默认Job和SupervisorJob的核心差异在于异常传播规则:
- 普通Job(默认):任意子协程抛出非
CancellationException的异常时,会立即取消父协程以及所有其他子协程,整个作用域直接失效。 - SupervisorJob:子协程抛出异常(包括非
CancellationException)时,仅终止该出错的子协程,父协程和其他兄弟子协程不受影响,实现了子协程的独立容错。
测试代码
val scope = CoroutineScope(Dispatchers.IO) Button(onClick = { scope.launch { launch { println("child 1 coroutine") delay(2.seconds) throw CancellationException() } delay(4.seconds) launch { println("child 2 coroutine") } } }) { Text(text = "Scope check") }
异常处理示例代码
val handler = CoroutineExceptionHandler { _, e -> println("handled: ${e.message}") } val scope = CoroutineScope(Dispatchers.IO + handler) Button( modifier = Modifier.padding(innerPadding), onClick = { scope.launch { supervisorScope { launch { println("child 1 coroutine") delay(1.seconds) throw Exception("Child 1 Exception") } delay(4.seconds) launch { println("child 2 coroutine") } } } }) { Text(text = "Scope check") }
内容的提问来源于stack exchange,提问作者PRATHIV
相关产品推荐
相关产品推荐

