launch, runBlocking, withContext, async

launch: 非阻塞的,launch会创建一个CoroutineContext,但是内部会直接执行。
runBlocking: 阻塞的,runBlocking会创建一个CoroutineContext,当内部的Coroutine执行完时,自己才执行完。
withContext 与 async 都可以返回耗时任务的执行结果。 一般来说,多个 withContext 任务是串行的, 且withContext 可直接返回耗时任务的结果。 多个 async 任务是并行的,async 返回的是一个Deferred,需要调用其await()方法获取结果。

我们看一下launch和runBlocking代码的区别。
先看launch,代码在这里:kotlinx.coroutines -> common -> Builders.common.kt

public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job {
    val newContext = newCoroutineContext(context)
    val coroutine = if (start.isLazy)
        LazyStandaloneCoroutine(newContext, block) else
        StandaloneCoroutine(newContext, active = true)
    coroutine.start(start, coroutine, block)
    return coroutine
}

很简单,创建了一个Coroutine,然后调用start启动这个Coroutine,最后返回了新创建的Coroutine.

再看看runBlocking的实现, runBlocking的实现在这里kotlinx.coroutines -> jvm -> Builders.kt

public fun  runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    val currentThread = Thread.currentThread()
    val contextInterceptor = context[ContinuationInterceptor]
    val eventLoop: EventLoop?
    val newContext: CoroutineContext
    if (contextInterceptor == null) {
        // create or use private event loop if no dispatcher is specified
        eventLoop = ThreadLocalEventLoop.eventLoop
        newContext = GlobalScope.newCoroutineContext(context + eventLoop)
    } else {
        // See if context's interceptor is an event loop that we shall use (to support TestContext)
        // or take an existing thread-local event loop if present to avoid blocking it (but don't create one)
        eventLoop = (contextInterceptor as? EventLoop)?.takeIf { it.shouldBeProcessedFromContext() }
            ?: ThreadLocalEventLoop.currentOrNull()
        newContext = GlobalScope.newCoroutineContext(context)
    }
    val coroutine = BlockingCoroutine(newContext, currentThread, eventLoop)
    coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
    return coroutine.joinBlocking()
}

在runBlocking的实现内部,创建了一个BlockingCoroutine, 最后调用了BlockingCoroutine的joinBlocking()方法。joinBlocking内部有一个while(true)的调用:

    fun joinBlocking(): T {
        registerTimeLoopThread()
        try {
            eventLoop?.incrementUseCount()
            try {
                while (true) {
                    @Suppress("DEPRECATION")
                    if (Thread.interrupted()) throw InterruptedException().also { cancelCoroutine(it) }
                    val parkNanos = eventLoop?.processNextEvent() ?: Long.MAX_VALUE
                    // note: process next even may loose unpark flag, so check if completed before parking
                    if (isCompleted) break
                    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
    }

其中还有一个关键调用if (isCompleted) break. Job的isCompleted属性被JobSupport类Override了。

// kotlinx.coroutines.JobSupport class
    public final override val isCompleted: Boolean get() = state !is Incomplete

你可能感兴趣的:(launch, runBlocking, withContext, async)