Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
698 views
in Technique[技术] by (71.8m points)

kotlin - Coroutines: runBlocking vs coroutineScope

I was reading Coroutine Basics trying to understand and learn it.

There is a part there with this code:

fun main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        println("Task from runBlocking")
    }

    coroutineScope { // Creates a new coroutine scope
        launch {
            delay(900L) 
            println("Task from nested launch")
        }

        delay(100L)
        println("Task from coroutine scope") // This line will be printed before nested launch
    }

    println("Coroutine scope is over") // This line is not printed until nested launch completes
}

The output goes like so:

Task from coroutine scope
Task from runBlocking
Task from nested launch
Coroutine scope is over

My question is why this line:

 println("Coroutine scope is over") // This line is not printed until nested launch completes

is called always last?

Shouldn't it be called since the:

coroutineScope { // Creates a new coroutine scope
    ....
}

is suspended?

There is also a note there:

The main difference between runBlocking and coroutineScope is that the latter does not block the current thread while waiting for all children to complete.

I dont understand how coroutineScope and runBlocking are different here? coroutineScope looks like its blocking since it only gets to the last line when it is done.

Can anyone enlighten me here?

Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't understand how coroutineScope and runBlocking are different here? coroutineScope looks like its blocking since it only gets to the last line when it is done.

From the perspective of the code in the block, your understanding is correct. The difference between runBlocking and coroutineScope happens at a lower level: what's happening to the thread while the coroutine is blocked?

  • runBlocking is not a suspend fun. The thread that called it remains inside it until the coroutine is complete.

  • coroutineScope is a suspend fun. If your coroutine suspends, the coroutineScope function gets suspended as well. This allows the top-level function, a non-suspending function that created the coroutine, to continue executing on the same thread. The thread has "escaped" the coroutineScope block and is ready to do some other work.

In your specific example: when your coroutineScope suspends, control returns to the implementation code inside runBlocking. This code is an event loop that drives all the coroutines you started within it. In your case, there will be some coroutines scheduled to run after a delay. When the time arrives, it will resume the appropriate coroutine, which will run for a short while, suspend, and then control will be again inside runBlocking.


While the above describes the conceptual similarities, it should also show you that runBlocking is a completely different tool from coroutineScope.

  • runBlocking is a low-level construct, to be used only in framework code or self-contained examples like yours. It turns an existing thread into an event loop and creates its coroutine with a Dispatcher that posts resuming coroutines to the event loop's queue.

  • coroutineScope is a user-facing construct, used to delineate the boundaries of a task that is being parallel-decomposed inside it. You use it to conveniently await on all the async work happening inside it, get the final result, and handle all failures at one central place.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...