簡體   English   中英

使用 withContext 的協程執行順序

[英]Coroutine Execution Order using withContext

幾天前我開始研究協程。 我明白了一點,但后來我看到一些代碼行提出了一些問題:

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}")
}

output 是:

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會在工作線程上創建一個新的協程,因此主線程上的任何正常 function 都會在啟動完成之前執行。 如果是這樣,我有點困惑為什么withContext代碼在launch代碼之前運行。 有人可以解釋嗎?

launch在工作線程上創建一個新的協程

當你按照這樣的句子構築你的想法時要小心。 協程不像普通代碼那樣在給定線程上運行。 這更像是將線程固定到 CPU 內核。 固定線程不擁有內核,操作系統只是確保,無論何時掛起然后恢復它,它都會將其調度到同一個 CPU 內核。

如果您使用“將線程調度到 CPU 內核”范例通過您的代碼 go,您可以輕松地看到您的 output 是如何有意義的:

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”才能接管以做出另一個調度決定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM