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

Kotlin协程使用async关键字仍串行执行问题排查咨询

问题原因
  • 默认调度器限制:runBlocking启动的协程默认继承当前调用线程作为调度器,属于单线程调度环境。你没有给async指定额外调度器的情况下,所有异步任务都会被调度到同一个线程执行,加上ActionReportGetter.getActions()是普通阻塞方法(非挂起函数),执行时会占用当前线程不释放,自然出现串行执行的效果。
  • 事务绑定特性不影响协程调度逻辑:Spring事务确实是和线程绑定的,但是它不会改变协程的调度规则,你当前串行问题和事务无关,不过后续并行实现后要注意事务上下文传播的问题。
解决方案
  1. 给async指定多线程调度器
    IO密集型任务(比如含数据库查询、接口调用)指定Dispatchers.IO,CPU密集型计算指定Dispatchers.Default,即可实现多线程并行执行。
  2. 注意事务上下文适配
    如果getActions()方法需要参与事务,由于子线程无法获取父线程的事务上下文,你需要给每个getActions()方法配置独立事务(比如Spring的@Transactional(propagation = Propagation.REQUIRES_NEW)),如果是只读逻辑不需要事务可以忽略该配置。
优化后代码示例
runBlocking {
    val actions = actionsReportGetters.map { actionReportGetter ->
        // 指定IO调度器实现多线程并行
        async(Dispatchers.IO) {
            getActions(actionReportGetter, abstractUser)
        }
    }.awaitAll().flatten()
    allActions.addAll(actions)
}

你也可以在suspend方法内部统一指定调度器,避免上层调用漏传调度器导致阻塞:

private suspend fun getActions(actionReportGetter: ActionReportGetter, traderUser: TraderUser): List<Action> {
    // 确保阻塞调用始终运行在IO调度器上,不会阻塞其他协程
    return withContext(Dispatchers.IO) {
        actionReportGetter.getActions(traderUser)
    }
}

内容的提问来源于stack exchange,提问作者Rory Towler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:24:02