使用withContext的Coroutine执行命令。

问题描述 投票:1回答:1

几天前我开始研究Coroutines。我了解了一点,但后来我看到一些代码行,提出了一些问题。

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 在worker线程上创建一个新的coroutine,因此主线程上的任何正常函数都会在启动完成前被执行。如果是这样的话,我就有点不明白了,为什么要用 withContext 代码运行 之前launch 代码。有人能解释一下吗?

kotlin kotlin-coroutines launch
1个回答
1
投票

launch 在工作线程上创建一个新的coroutine

当你按照这样的句子来构思的时候要小心。一个coroutine并不像普通代码那样运行在一个给定的线程上。它更像是将一个线程钉在一个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}")
}

在这幅图中,你只需加上一个事实,即 "操作系统 "无法先发制人地暂停一个 "线程",只有当 "线程 "暂停时,"操作系统 "才能接管,做出另一个调度决定。

© www.soinside.com 2019 - 2024. All rights reserved.