使用withContext的协同程序执行顺序

时间:2020-05-17 01:59:46

标签: kotlin kotlin-coroutines launch

几天前,我开始调查协程。我有点了解,但是随后我看到了一些代码行,引发了一些问题:

<dark-theme v-if="theme == 'dark'"/>
<light-theme v-if="theme == 'light'"/>

输出为:

import kotlinx.coroutines.*

fun main() = runBlocking {

    launch {

        println("in sub coroutine ${Thread.currentThread().name}")
    }
    println("before coroutine in main ${Thread.currentThread().name}")
    withContext(Dispatchers.IO) {
        println("hello from coroutine ${Thread.currentThread().name}")
        delay(1500)
        println("hello from coutoutine after delay ${Thread.currentThread().name}")
    }
    println("after coroutine in main ${Thread.currentThread().name}")
}

据我了解,before coroutine in main main @coroutine#1 in sub coroutine main @coroutine#2 hello from coroutine DefaultDispatcher-worker-1 @coroutine#1 hello from coutoutine after delay DefaultDispatcher-worker-1 @coroutine#1 after coroutine in main main @coroutine#1 在工作线程上创建了一个新的协程,因此主线程上的所有常规函数都在启动完成之前执行。如果是这样,我有点困惑为什么launch代码在withContext代码之前 运行。有人可以解释吗?

1 个答案:

答案 0 :(得分:1)

launch在辅助线程上创建新的协程

当根据这样的句子来表达自己的想法时,请务必小心。协程不像普通代码那样在给定线程上运行。这更像是将线程固定到CPU内核。固定线程不拥有内核,操作系统只是确保只要挂起然后恢复它,它将把它调度到同一CPU内核。

如果使用“将线程调度到CPU核心”范例来遍历代码,则可以轻松地看到输出的含义:

runBlocking { // Create a context within which "threads" are pinned
              // to a single "core", let's call it "Main Core"
    launch { // Start another "thread" pinned to "Main Core". The "thread" is
             // in a suspended state, waiting for "Main Core" to get free
        println("in sub coroutine ${Thread.currentThread().name}")
    }
    // `launch` is just a function, it completed after creating the new "thread",
    //  move on to the code below it
    println("before coroutine in main ${Thread.currentThread().name}")
    // Start a context where "threads" are pinned to another "core", the 
    // "IO Core". It executes its "threads" concurrently to "Main Core".
    // However, the particular "thread" that creates the context gets suspended
    // until it is done. Other "threads" pinned to "Main Core" can run.
    withContext(Dispatchers.IO) {
        println("hello from coroutine ${Thread.currentThread().name}")
        delay(1500)
        println("hello from coutoutine after delay ${Thread.currentThread().name}")
    }
    // Now the "thread" that created the "IO Core" context can go on.
    println("after coroutine in main ${Thread.currentThread().name}")
}

在这张图片中,您只需要添加以下事实:“ OS”无法抢先挂起“线程”,只有当“线程”挂起自身时,“ OS”才能接管做出另一个调度决策。 / p>