如何在子协程抛出异常时让其他子协程继续执行?
解决子协程异常不影响其他子协程执行的问题
你的代码核心问题在于:两个子协程嵌套在scope.launch创建的普通Job协程下,而非直接挂载到带有SupervisorJob的CoroutineScope上。普通Job的特性是子协程异常会传播到父协程,导致父协程取消所有同级子协程,所以子协程2抛出异常时,外层launch协程会被取消,连带终止子协程1。
要实现子协程2崩溃时子协程1继续执行,只需将两个子协程直接作为scope的顶级子协程启动,而非嵌套在另一个launch中:
suspend fun main() { val context = Dispatchers.Default + SupervisorJob() val scope = CoroutineScope(context = context) // 直接在scope下启动两个子协程 val job1 = scope.launch { repeat(25) { println("child 1 $it") delay(25) } } val job2 = scope.launch { repeat(20) { println("child 2 $it") delay(18) if (it == 16) throw Exception("aaa") } } job1.join() job2.join() // 等待两个子协程都完成(即使job2异常) println("Main finished") }
关键原理说明
SupervisorJob的作用是隔离子协程的异常传播:当某个子协程抛出未捕获异常时,只会取消该子协程本身,不会影响其他同级子协程或父协程。- 必须确保两个子协程是
SupervisorJob作用域的直接子协程,而非嵌套在普通Job协程下,否则隔离规则不生效。
如果需要处理子协程2的异常,可在其launch块内添加try-catch,避免异常被协程异常处理器捕获(虽然不影响其他协程,但能更优雅地处理错误):
val job2 = scope.launch { try { repeat(20) { println("child 2 $it") delay(18) if (it == 16) throw Exception("aaa") } } catch (e: Exception) { println("子协程2捕获异常:${e.message}") } }
内容的提问来源于stack exchange,提问作者Teddy Consultant
相关产品推荐
相关产品推荐

