Kotlin协程如何实现单个任务异常时其余任务全部执行完毕
根因说明
默认协程作用域使用普通Job作为上下文元素,子协程抛出未捕获异常时会向上传播,触发父协程的取消逻辑,父协程取消会连带终止所有仍在运行的子协程,所以你提供的示例代码运行时count只累加到2就停止了。
解决方案
方案1:使用supervisorScope隔离子协程失败影响
supervisorScope内部使用SupervisorJob作为上下文,子协程的失败不会向上传播取消父作用域,也不会影响其他同级子协程的运行,是实现需求最简便的方式。
修改后代码如下:
import kotlinx.coroutines.* import java.util.concurrent.atomic.AtomicInteger fun main() = runBlocking(Dispatchers.Default) { val count = AtomicInteger(0) // 用supervisorScope包裹异步任务创建逻辑 supervisorScope { val deferred = List(10) { async { if (count.incrementAndGet() == 2) throw Exception("test") } } try { deferred.awaitAll() } catch (e: Exception) { println("Exception caught") } } println(count) }
这个写法中所有async都属于supervisorScope的子协程,第二个任务抛异常只会终止自身,剩下9个任务会正常执行完成,最终count输出10。
方案2:单个任务内部捕获异常,避免向上传播
如果需要单独处理每个任务的异常,也可以直接在async的代码块中捕获异常,从根源上避免未捕获异常向上传递触发取消逻辑。
代码示例如下:
import kotlinx.coroutines.* import java.util.concurrent.atomic.AtomicInteger fun main() = runBlocking(Dispatchers.Default) { val count = AtomicInteger(0) val deferred = List(10) { async { runCatching { if (count.incrementAndGet() == 2) throw Exception("test") }.onFailure { println("单个任务执行失败: ${it.message}") } } } deferred.awaitAll() println(count) }
这个写法里每个任务的异常都被runCatching捕获处理,不会触发协程取消,所有任务都会执行完成,最终count输出10。
内容的提问来源于stack exchange,提问作者k314159
相关产品推荐
相关产品推荐

