如何 运行 在 Kotlin 中并发阻塞 Java 代码?
How to run blocking Java code concurrently in Kotlin?
我正在做一个新的副项目,目标是更深入地学习 Kotlin,但我在弄清楚如何将 Kotlin 风格的并发与未考虑协程编写的代码混合时遇到了一些麻烦(JOOQ在这种情况下)。下面的函数在我的一个 DAO 中,在那个映射块中,我想更新数据库中的一堆行。在这个具体的例子中,更新实际上依赖于前一个完成,所以它需要按顺序完成,但我感兴趣的是如何将这段代码修改为 运行 并行更新,因为那里毫无疑问,我拥有的用例不需要按顺序 运行。
suspend fun updateProductChoices(choice: ProductChoice) = withContext(Dispatchers.IO) {
ctx().transaction { config ->
val tx = DSL.using(config)
val previousRank = tx.select(PRODUCT_CHOICE.RANK)
.from(PRODUCT_CHOICE)
.where(PRODUCT_CHOICE.STORE_PRODUCT_ID.eq(choice.storeProductId))
.and(PRODUCT_CHOICE.PRODUCT_ID.eq(choice.productId))
.fetchOne(PRODUCT_CHOICE.RANK)
(previousRank + 1..choice.rank).map { rank ->
tx.update(PRODUCT_CHOICE)
.set(PRODUCT_CHOICE.RANK, rank - 1)
.where(PRODUCT_CHOICE.PRODUCT_ID.eq(choice.productId))
.and(PRODUCT_CHOICE.RANK.eq(rank))
.execute()
}
}
}
最好的方法是将 transaction
lambda 包装在 runBlocking
中,并将每个 update
包装在 async
中,然后 awaitAll
结果?还可能值得注意的是,JOOQ 查询支持 executeAsync()
其中 returns a CompletionStage
.
是的,使用 JOOQ 的 executeAsync
。使用 executeAsync
,您可以删除 withContext(Dispatchers.IO)
,因为调用不再阻塞。
kotlinx-coroutines-jdk8
库包括与 CompletionStage
的协程集成,因此您可以对其执行暂停 await
(docs)。
要并行执行更新,请注意同一个库可以将 CompletionStage
转换为 Deferred
(docs)。因此,如果将对 execute
的调用更改为 executeAsync().asDeferred()
,您将获得 Deferred
的列表,您可以在其上 awaitAll()
.
我正在做一个新的副项目,目标是更深入地学习 Kotlin,但我在弄清楚如何将 Kotlin 风格的并发与未考虑协程编写的代码混合时遇到了一些麻烦(JOOQ在这种情况下)。下面的函数在我的一个 DAO 中,在那个映射块中,我想更新数据库中的一堆行。在这个具体的例子中,更新实际上依赖于前一个完成,所以它需要按顺序完成,但我感兴趣的是如何将这段代码修改为 运行 并行更新,因为那里毫无疑问,我拥有的用例不需要按顺序 运行。
suspend fun updateProductChoices(choice: ProductChoice) = withContext(Dispatchers.IO) {
ctx().transaction { config ->
val tx = DSL.using(config)
val previousRank = tx.select(PRODUCT_CHOICE.RANK)
.from(PRODUCT_CHOICE)
.where(PRODUCT_CHOICE.STORE_PRODUCT_ID.eq(choice.storeProductId))
.and(PRODUCT_CHOICE.PRODUCT_ID.eq(choice.productId))
.fetchOne(PRODUCT_CHOICE.RANK)
(previousRank + 1..choice.rank).map { rank ->
tx.update(PRODUCT_CHOICE)
.set(PRODUCT_CHOICE.RANK, rank - 1)
.where(PRODUCT_CHOICE.PRODUCT_ID.eq(choice.productId))
.and(PRODUCT_CHOICE.RANK.eq(rank))
.execute()
}
}
}
最好的方法是将 transaction
lambda 包装在 runBlocking
中,并将每个 update
包装在 async
中,然后 awaitAll
结果?还可能值得注意的是,JOOQ 查询支持 executeAsync()
其中 returns a CompletionStage
.
是的,使用 JOOQ 的 executeAsync
。使用 executeAsync
,您可以删除 withContext(Dispatchers.IO)
,因为调用不再阻塞。
kotlinx-coroutines-jdk8
库包括与 CompletionStage
的协程集成,因此您可以对其执行暂停 await
(docs)。
要并行执行更新,请注意同一个库可以将 CompletionStage
转换为 Deferred
(docs)。因此,如果将对 execute
的调用更改为 executeAsync().asDeferred()
,您将获得 Deferred
的列表,您可以在其上 awaitAll()
.