runBlocking为什么是堵塞的
- 按惯例先上runBlocking源码
public fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T {
//省略部分代码
val coroutine = BlockingCoroutine<T>(newContext, currentThread, eventLoop)//1
coroutine.start(CoroutineStart.DEFAULT, coroutine, block)//2
return coroutine.joinBlocking()//3
}
- 注释1: 创建BlockingCoroutine对象,看名字就知道跟堵塞有关;
- 注释2: 主要是创建、启动协程,具体就不展开说明,可以看下我其他分析的文章;
- 注释3: 对比CoroutineScope.launch直接返回coroutine,runBlocking返回coroutine.joinBlocking()函数结果,猜测悬念就是在这里;
猜测:协程已经启动了,但是runBlocking函数一直没有返回,那么就是coroutine.joinBlocking()一直没有返回,它在等待某个信号;
- joinBlocking源码
fun joinBlocking(): T {
registerTimeLoopThread()
try {
eventLoop?.incrementUseCount()
try {
while (true) {
if (Thread.interrupted()) throw InterruptedException().also { cancelCoroutine(it) }
if (isCompleted) break//1
parkNanos(this, parkNanos)
}
} finally { // paranoia
eventLoop?.decrementUseCount()
}
} finally { // paranoia
unregisterTimeLoopThread()
}
// now return result
val state = this.state.unboxState()
(state as? CompletedExceptionally)?.let { throw it.cause }
return state as T
}
- 看到这个判断了吗?在协程isCompleted 为true的情况下才会返回,要不然一直在while的循环里面,其实还有一个条件可以让函数返回,就是线程中断了(Thread.interrupted())。
总结
- runBlocking之所以是堵塞的,是因为runBlocking一直在等待中断或完成的结果。
- 其实我之前也不爱看源码,觉得很痛苦。后来跟着大佬们的分析,慢慢也觉得看源码还有点意思。
以上分析有不对的地方,请指出,互相学习,谢谢哦!