Kotlin中runBlocking会阻塞当前线程,使用它的实际作用是什么?
一、Kotlin runBlocking 相关疑问
1. 相比普通函数,使用runBlocking的实际收益
你示例中调用的数据库查询是suspend挂起函数,这类函数只能在协程作用域或其他挂起函数中执行,普通函数环境下无法直接调用。runBlocking的核心作用是桥接普通阻塞代码和挂起代码,为挂起函数提供运行环境,这是你能直接调用数据库查询挂起函数的前提。
除此之外还有两个明确收益:
- 代码可读性更高:不需要手动管理线程池、Future、回调逻辑,用同步写法就能完成异步操作,避免嵌套回调的回调地狱问题
- 可轻松实现并发优化:
runBlocking内部的协程支持挂起,如果你需要执行多个查询任务,可以用async+await实现并发,总耗时等于最长单个任务的耗时,远高于普通函数串行执行的效率
2. runBlocking会阻塞线程,为什么属于异步代码范畴
这个说法存在误解:runBlocking本身是协程框架的桥接工具,不属于异步代码,它内部运行的挂起逻辑才是异步非阻塞的。
你之前理解的「异步代码是为了避免线程阻塞」,指的是协程内部的挂起操作不会占用线程资源:比如执行IO等待时,线程可以被释放去处理其他任务,等IO完成再回来继续执行。而runBlocking的阻塞是对外的:它会等待内部所有协程任务执行完成才会返回,所以外部调用它的线程会被阻塞,这和它内部的异步逻辑并不冲突。
注意如果你的代码运行在Android、桌面端的UI线程,不应该用runBlocking,会导致界面无响应;如果是后端业务线程、命令行工具主线程等允许阻塞等待结果的场景,这种写法是合理的。
二、JavaScript async/await 相关疑问
首先纠正一个核心误区:JS的await并不会阻塞线程,它只会阻塞当前async函数内部的后续代码执行,整个JS的事件循环完全不会被卡住。
比如你在前端用await发起网络请求时,await后的代码会等待请求返回后再执行,但这段时间页面的点击响应、定时器任务都可以正常运行,不会出现UI无响应的问题。如果你用传统的同步XMLHttpRequest发请求,才会真的阻塞整个JS线程,导致页面卡死。
async/await的本质是Promise的语法糖,核心收益是把嵌套的Promise回调改成同步式的写法,大幅提升代码可读性和可维护性,同时完全保留了异步代码不阻塞主线程的优势。
内容的提问来源于stack exchange,提问作者Charan Sai

