You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 12:12:03