美文网首页
Kotlin 协程奇闻录之作用域构建器

Kotlin 协程奇闻录之作用域构建器

作者: 全汪汪 | 来源:发表于2020-04-16 21:09 被阅读0次

    奇闻描述

    事情是这样的,最近又重新学习协程,毕竟现在协程也相对以前较为完善了。没错他来了,之前每次看到作用域构建器小节都满脸疑惑,也就是runningBlock和 coroutineScope的区别。以下是官方的示例:

    import kotlinx.coroutines.*
    
    fun main() = runBlocking { // this: CoroutineScope
        launch { 
            delay(200L)
            println("Task from runBlocking")
        }
        
        coroutineScope { // 创建一个协程作用域
            launch {
                delay(500L) 
                println("Task from nested launch")
            }
        
            delay(100L)
            println("Task from coroutine scope") // 这一行会在内嵌 launch 之前输出
        }
        
        println("Coroutine scope is over") // 这一行在内嵌 launch 执行完毕后才输出
    }
    

    输出顺序是这样的:
    Task from coroutine scope
    Task from runBlocking
    Task from nested launch
    Coroutine scope is over

    但是程序没有运行之前,我感觉顺序是这样的:
    Coroutine scope is over
    Task from coroutine scope
    Task from runBlocking
    Task from nested launch

    放到最外层runBlocking的代码应该先运行才对的,因为官方都说了嘛,协程是不堵塞线程的,所以runBlocking应该不会堵塞,直接运行其最外围代码才对。

    于是我看了下官方的解释:

    runBlocking方法会阻塞当前线程来等待, 而 coroutineScope只是挂起,会释放底层线程用于其他用途。 由于存在这点差异,runBlocking是常规函数,coroutineScope而是挂起函数。

    我寻思啥是挂起函数啊,话说挂起函数最直观的不就是suspend修饰符的方法吗,这有什么关系。
    然后点开coroutineScope源码:

    public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R =
        suspendCoroutineUninterceptedOrReturn { uCont ->
            val coroutine = ScopeCoroutine(uCont.context, uCont)
            coroutine.startUndispatchedOrReturn(coroutine, block)
        }
    

    行吧,原来你是个挂起函数,suspend 修饰符。
    但我依旧有点懵逼,还是没清楚是怎么回事。
    于是我尝试用自己写的挂起函数来代替:

        fun corKx() {
            runBlocking {
                launch {
                    delay(200L)
                    println("Task from runBlocking")
                }
                Ktcomputer()
                println("Coroutine scope is over") // 这一行在内嵌 launch 执行完毕后才输出
            }
        }
    
        //自己写的代替coroutineScope的挂起函数,削减了一个子协程,因为这里只是探讨coroutineScope
        suspend fun Ktcomputer(){
            delay(500L)
            println("Task from nested launch")
        }
    

    然后结果是:
    Task from runBlocking
    Task from nested launch
    Coroutine scope is over

    懂了吗?
    嗯...没懂,这么说吧为什么要定义挂起函数,是因为我要需要在函数里要用到挂起函数。
    所以上面实际上可以把自己定义的挂起函数内容直接放到runBlocking里也就是这样:

    fun corKx() {
            runBlocking {
                launch {
                    delay(200L)
                    println("Task from runBlocking")
                }
                delay(500L)
                println("Task from nested launch")
                println("Coroutine scope is over") // 这一行在内嵌 launch 执行完毕后才输出
            }
        }
    

    懂了吧...直接放了进来之后就很明显了。
    其实这已经扯到了挂起函数去了...

    相关文章

      网友评论

          本文标题:Kotlin 协程奇闻录之作用域构建器

          本文链接:https://www.haomeiwen.com/subject/mmvdvhtx.html