【问题标题】:Limit on the number of coroutines协程数量限制
【发布时间】:2023-01-03 03:03:48
【问题描述】:

我有代码,是这样的:

entities.forEach {
    launch() {
        doingSomethingWithDB(it)
    }
}

suspend fun doingSomethingWithDB(entity) {
    getDBConnectionFromPool()
    // doing something
    returnDBConnectionToPool()
}

当实体数量超过数据库连接池的大小时(我使用 HikariCP),我得到错误 - Connection is not available...。即使我只使用单线程(例如-Dkotlinx.coroutines.io.parallelism=1),我还是会收到这个错误。

在处理外部资源(如固定大小的数据库连接池)时,是否有限制并行协程数量的最佳实践?

【问题讨论】:

  • “做某事”部分是调用其他挂起函数,还是仅调用阻塞函数?如果它正在调用挂起函数,那么这些挂起函数可能不会使用您限制并行性的任何调度程序来完成工作。并请显示您限制并行度的代码。
  • @Tenfour04“做某事”可以调用其他挂起函数和/或阻塞函数(读取或写入数据库)。我使用 JVM 标志 -Dkotlinx.coroutines.io.parallelism=1
  • 这回答了你的问题了吗? how to cap kotlin coroutines maximum concurrency
  • 据我所知,这只会限制 IO 调度程序中的线程数。但是只要在任何协程中有一个挂起点,它们仍然可以交换进出服务。它们可能不会在单独的线程上并行运行,但它们仍然是并发的。您需要使用不同的策略。此外,如果您在编译器参数中限制并行性,就会搞乱项目中任何其他协程的功能。
  • 如果您希望这些操作一次运行一个,为什么要启动多个协程?我会将 for 循环移动到一个协程中。

标签: kotlin kotlin-coroutines connection-pooling hikaricp


【解决方案1】:

由于您的 doingSomethingWithDB() 在开始/结束时手动获取和释放资源,因此在这种情况下限制并行度是不够的 - 我们需要限制并发度。最简单的方法是使用Semaphore

val semaphore = Semaphore(8)

suspend fun doingSomethingWithDB(entity) {
    semaphore.withPermit {
        getDBConnectionFromPool()
        // doing something
        returnDBConnectionToPool()
    }
}

解释几句:因为协程可以挂起和线程切换,即使我们限制调用doingSomethingWithDB()的协程的并行度,这个函数仍然可以并发调用任意次数。并行性仅表示在特定时刻可以运行多少个协程,但如果其中任何一个挂起,则可以继续执行其他协程。

【讨论】:

    猜你喜欢
    • 2020-05-01
    • 2016-01-26
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多