Kotlin - runBlocking为什么是堵塞的

586 阅读1分钟
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一直在等待中断或完成的结果。
  • 其实我之前也不爱看源码,觉得很痛苦。后来跟着大佬们的分析,慢慢也觉得看源码还有点意思。

以上分析有不对的地方,请指出,互相学习,谢谢哦!