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

Spring Boot非响应式环境下Kotlin协程无法并行执行问题

问题:Spring Boot非响应式环境下Kotlin协程无法并行执行

我正在使用Spring Boot和Kotlin构建后端应用,希望为特定方法实现并行执行。尝试使用协程后,底层方法仍同步执行。

实现代码:

fun getXsByIds(xIds: List<String>): List<X> {
        val xList = ArrayList<X>();
        runBlocking {
            val promises = xIds.map {
                async {
                    getXById(it)
                }
            };
            
            xList.addAll((promises.awaitAll()).filterNotNull())
        }
        return xList;
    }

    fun getXById(xId: String): X? {
        // 该方法向数据库发起请求
    }

在getXById中添加日志后:

fun getXById(xId: String): X? {
        print("start");
        // 该方法向数据库发起请求
        print("end");
    }

输出为:

start
end
start
end
start
end
...

当前环境为Spring Boot非响应式,采用线程每请求(Thread per request)模式。请问为何协程无法并行执行?


原因分析
  • runBlocking默认使用单线程上下文:runBlocking启动时默认绑定当前调用线程,内部所有协程(包括async创建的)都会在这个单线程的事件循环中执行,本质是串行调度,无法实现并行。
  • getXById是阻塞式同步方法:该方法内部是阻塞的数据库请求,会占用当前线程直到操作完成,即使协程调度逻辑支持并行,单线程环境下也没有机会同时执行多个协程任务。

解决方案

要实现并行,需给协程指定多线程的Dispatcher,推荐使用Dispatchers.IO——它是专门为处理阻塞IO操作设计的线程池,适配数据库请求这类场景。

修改后的代码:

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking

fun getXsByIds(xIds: List<String>): List<X> {
    val xList = ArrayList<X>()
    runBlocking {
        val promises = xIds.map {
            // 指定Dispatchers.IO作为协程上下文
            async(Dispatchers.IO) {
                getXById(it)
            }
        }
        xList.addAll(promises.awaitAll().filterNotNull())
    }
    return xList
}

fun getXById(xId: String): X? {
    print("start")
    // 数据库请求操作
    print("end")
}

修改后,每个async协程会被调度到Dispatchers.IO线程池的不同线程执行,阻塞的数据库请求会在多线程上并行处理,日志输出会呈现出并行执行的特征(比如start start start end end end)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:13:29