Sping Boot Kotlin协程不并行运行

9jyewag0  于 2023-11-21  发布在  Kotlin
关注(0)|答案(2)|浏览(149)

我正在用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? {
        // This method makes request to database
    }

字符串
当我像这样把日志放在getXById方法中时,

fun getXById(xId: String): X? {
        print("start");
        // This method makes request to database
        print("end");
    }


我得到这个输出

start
end
start
end
start
end
...


为什么我的协程不能并行工作?这是在Spring Boot 。不是被动的。线程每请求的风格。

flmtquvp

flmtquvp1#

调用async而不指定任何协程元素意味着它将从父协程继承所有协程元素(作业除外)。这将导致您的“runBlocking”调用在runBlocking的阻塞分派器上执行。
尝试使用async(Dispatchers.Default) { ... }代替。

u1ehiz5o

u1ehiz5o2#

runBlocking创建了一个ad-hoc协程调度器,它使用调用runBlocking的线程来处理所有协程。这使它成为一个单线程调度器,这并不意味着它不能并发。它可以很好地运行任何数量的并发协程。
但是,单线程分派器只有在使用挂起、非阻塞IO时才有效,而您的情况似乎并非如此。
这就是为什么你必须显式地指定IO调度器,它被设计为支持阻塞代码:

runBlocking(Dispatchers.IO) {
    ...
}

字符串
虽然这解决了你眼前的问题,但你应该问问自己,如果你实际上没有使用暂停IO,为什么还要引入复杂的协同程序?坚持使用普通的Java Executor也会得到同样的结果。

相关问题