kotlin - 尝试调用运行阻塞时,带有 Coroutines 的 Kotlin Vertx 阻塞
问题描述
我正在使用公开了回调函数的第三方库。回调函数将在成功时调用。回调函数不是挂起函数,但是当我尝试在非挂起函数内部进行调用以返回挂起函数的结果时,该函数使用 aysnc 和 await 进行 IO 调用,调用永远不会被强制执行。下面我想出了一个简单的代码片段来演示这个问题。
open class TestVerticle: CoroutineVerticle() {
override suspend fun start() {
awaitBlockingExample()
}
fun awaitBlockingExample():String {
val future= async(vertx.dispatcher()) {
makeSuspendFunCall()
}
val result:String= runBlocking(vertx.dispatcher()){future.await()}
println(" The final Result is $result")
return result
}
suspend fun makeSuspendFunCall():String{
println("Comming here 3")
delay(500)
val resp="Test"
return resp
}
}
fun main(args: Array<String>) = runBlocking {
Vertx.vertx().deployVerticle("TestVerticle")
}
如果我删除 makeSuspendFunCall 中的延迟函数,程序运行良好,但如果我添加延迟函数,它会挂起。我实际上是在这里使用延迟函数模拟挂起函数网络调用。在这种情况下,如何从 awaitBlockingExample 获得结果?我清楚地明白,通过将 awaitBlockingExample 作为挂起函数,我可以完成这项工作并删除异步并在内部运行阻塞调用。但是这里 awaitBlockingExample (非挂起函数)代表了一个由本方库提供的实现,它在我们的实现中被覆盖。比如guava缓存提供了reload函数,我想重写reload函数(非挂起函数),并从reload方法中调用协程函数来刷新数据库或网络调用的缓存值。
解决方案
问题是它vertx.dispatcher()
使用单个线程作为事件循环并runBlocking
阻止该线程。
细节:
您的awaitBlockingExample()
函数正在此 Vertx 事件循环线程上运行,因为它是从suspend start()
函数触发的。如果你调用runBlocking()
这个 Vertx 线程被阻塞并且永远不会被释放。但是你的其他协程,例如async()
,现在没有线程来完成他们的工作。
解决方案:
我假设awaitBlockingExample
fromstart
函数的调用仅在此示例中发生。实际上,我会假设外部回调使用自己的线程。那么就完全没有问题了,因为现在外线程被阻塞了:
override suspend fun start() {
//simulate own thread for external callback
thread {
awaitBlockingExample()
}
}
fun awaitBlockingExample():String {
val future= async(vertx.dispatcher()) {
makeSuspendFunCall()
}
val result:String= runBlocking(vertx.dispatcher()){future.await()}
println(" The final Result is $result")
return result
}
BTW:你不需要async()
块,你可以直接调用makeSuspendFunCall()
fromrunBlocking()
fun awaitBlockingExample():String = runBlocking(vertx.dispatcher()){
val result = makeSuspendFunCall()
println(" The final Result is $result")
result
}
推荐阅读
- django - 删除django中的多行
- python - 在 Python 中,如何将符号转换为表情符号?
- python - 用 pyplot 在前景中绘制更近的线条
- email - SpamAssassin:阻止来自除某些域之外的所有域的电子邮件到特定用户
- unity3d - Unity - 命令行性能
- xslt - 使用 XSLT 将 xsd:complex-type 元素复制到另一个 xsd:complex-type 元素
- c# - C# 中的 LoadLibraryEx 函数问题
- python - finally 总是在 try 块返回之前运行,那么为什么 finally 块中的更新不会影响 try 块返回的变量的值?
- javascript - 在反应应用程序的函数调用中使用时,Axios post 不返回数据
- javascript - JavaScript 函数不适用于第二个 HTML 文件,因为它是由第一个 HTML 文件中的按钮触发的