使用 Kotlin 协程加载多个 JPA 实体

Load several JPA entities using Kotlin coroutine

我正在尝试在应用层使用 Hibernate 和 Kotlin 协程加载多个实体。做这样的事情。

fun load() : SomeData {

    val steps = someFunctionCallToGetSteps()

    val stepCollection : List<Step> = MutableList()

    runBlocking {

        for (step in steps) {

            val s = async { getStepData(step) }
            payers.add(s.await())
        }
    }
}

private suspend fun getStepData(step : Int) : Iterable<Step> {

    return someComputation()
}

但是这种方法是不正确的,因为我立即使用 await 所以它不是异步的。我被告知要收集所有延迟并使用 awaitAll 但我在任何地方都找不到它的任何例子。这能做到吗?

将每个 s 放入列表并在 for 循环之外执行 awaitAll(yourListOfs)

如果我做对了,您需要这样的东西来实现您的目标。调用多个 async 构建器,然后将 Deferred 映射到 Step。与其使用 Dispatchers.Default 不如 create your own dispatcher.

data class Step(val step: Int)

fun main(args: Array<String>) = runBlocking {

    val steps = someFunctionCallToGetSteps()

    val result = coroutineScope {
        val defferedSteps = steps.map {
            async(Dispatchers.Default) {
                getStepData(it)
            }
        }
        defferedSteps.map { deferred -> deferred.await() }
    }

    for (step in result)
        println(step)
}

fun someFunctionCallToGetSteps(): List<Int> {
    return listOf<Int>(1, 2, 3, 4)
}

suspend fun getStepData(step: Int): Step {
    println("[${Thread.currentThread().name}] loading...")
    delay(500)
    return Step(step)
}

终于解决了这个问题。我正在发布答案,希望其他人可以从中受益。

fun load() : List<Result> {

    val steps = someFunctionCallToGetSteps()
    val result: List<Result> = ... 

    runBlocking {

        val stepsDeferred = steps.map { async { getStepData(it) } }

        stepsDeferred.awaitAll().forEach { result.add(it) }
    }

    return result
}

private suspend fun getStepData(step : Int) : Iterable<Step> {

    return someComputation()
}