如果我在Kotlin协程中编写阻塞代码,它仍然会阻塞线程吗?



这个问题是在与同事广泛讨论后产生的,

问题如下:

在一个带有continuation的suspendCoroutine块中调用同步方法之前我在做什么:

private suspend fun <T : Any> request(queryRequest: GraphQLQueryRequest<T>): T? = suspendCoroutine { continuation ->
val response = graphqlClient.executeQuery(queryRequest.query, queryRequest.variables, executor)
val item = response.extractValueAsObject("data.${queryRequest.pathAccessor}", queryRequest.type.java)
continuation.resume(item)
}

他声称我的代码没有阻止线程被阻塞,整个进程必须等待我的协程恢复来释放线程。

他的提议:

private suspend fun <T : Any> request(queryRequest: GraphQLQueryRequest<T>): T? {
val response = graphqlClient.reactiveExecuteQuery(queryRequest.query, queryRequest.variables, executor)
return response.awaitSingle().extractValueAsObject("data.${queryRequest.pathAccessor}", queryRequest.type.java)
}

reactiveExecuteQuery()将返回WebFlux Mono,然后我们调用.awaitSingle()将Mono转换为挂起函数,他声称这个方法不像第一个方法那样不会阻塞线程,一切都会正常工作。

根据suspendCoroutine

的文档Obtains the current continuation instance inside suspend functions and suspends the currently running coroutine.

有更深入了解Kotlin协程的人知道这些解决方案是否真的提供了不同的结果吗?在没有阻塞线程的阻塞方面?

如果这不是suspendCoroutine的用例,它会是什么?

提前感谢您的回复:)

你的同事通常是对的,正如@Martin Tarjányi已经提到的。

awaitSingle是一个挂起函数,您可以在文档中看到。这意味着调用它将挂起协程,但其他协程仍然可以在同一个Dispatcher上运行。

有时候,当库只提供阻塞API时,没有其他解决方案,但是您应该在相对较大的线程池上运行协程。对于您的代码,您将在调用request()的同一个调度程序上运行,通常是Dispatchers.Default,它等于您的内核数量(如果您在单核CPU上运行,则为2)。

最新更新