You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

协程中用runInterruptible调用ListenableFuture.get()是否阻塞线程?如何非阻塞?

问题解答

问题1:即使在runInterruptible中,协程内调用com.google.common.util.concurrent.ListenableFuture.get()是否会阻塞线程?

会阻塞线程。runInterruptible仅为阻塞操作提供协程中断支持——当协程被取消时,它会中断执行阻塞调用的线程,但**get()本身仍是阻塞式调用**,会占用Dispatchers.IO线程池中的一个线程,直到ListenableFuture执行完成。

问题2:使用gRPC返回的ListenableFuture并调用其get()方法,是否会阻塞执行该调用的线程?或是因为处于协程中,线程会被释放,仅在网络响应到达时才恢复?

会阻塞线程。无论是否处于协程环境,ListenableFuture.get()都是原生的阻塞方法,会占用当前执行线程直到gRPC响应返回。协程不会自动将阻塞调用转为非阻塞挂起,runInterruptible仅增加了中断能力,并未改变get()阻塞线程的本质,线程不会被释放。

是否存在非阻塞的使用方式?

存在。可以借助kotlinx-coroutines-guava库的扩展函数,将ListenableFuture转换为协程的Deferred对象,实现真正的非阻塞等待。

修改后的代码示例:

@RestController
class SomeController(
    private val stub: YourGrpcStubType
) {
    @PostMapping("/create-table")
    suspend fun createTable(@RequestBody request: CreateCDPTableRequest): CreateTableResponse {
        val responseFuture: ListenableFuture<Response> = stub.someGrpcCall(requestBuilder.build())
        // 将ListenableFuture转为Deferred,非阻塞等待结果
        val response = responseFuture.asDeferred().await()
        // 转换并返回响应
        return mapToCreateTableResponse(response)
    }
}

使用asDeferred()后,await()会挂起协程而非阻塞线程,线程会被放回Dispatchers.IO线程池复用,直到gRPC响应到达后协程才恢复执行。

内容的提问来源于stack exchange,提问作者Guy Assaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:30:10