coroutineScope 是一个挂起函数

2026-07-23 09:37:43 来源: 互联网 点击数: 

suspend fun main() {
    // Root of the coroutine subtree
    coroutineScope { // this: CoroutineScope
        this.launch {
            this.launch {
                delay(2.seconds)
                println("Child of the enclosing coroutine completed")
            }
            println("Child coroutine 1 completed")
        }
        this.launch {
            delay(1.seconds)
            println("Child coroutine 2 completed")
        }
    }
    // Runs only after all children in the coroutineScope have completed
    println("Coroutine scope completed")
}
为什么不是先执行   println("Coroutine scope completed")

 

这段代码的执行顺序是由 Kotlin 协程的结构化并发机制决定的。核心原因是 coroutineScope 是一个挂起函数,它会等待其内部所有子协程完成之后才会继续执行后面的代码。
让我们逐步分析执行流程:

  1. 进入 coroutineScope
    • 程序执行到 coroutineScope { ... } 时,这是一个挂起点,会创建一个新的协程作用域。
  2. 启动第一个子协程
    • this.launch { ... } 启动了一个子协程(称为 A)。
    • 在 A 内部:
      • 首先遇到 println("Child coroutine 1 completed"),所以立即打印 "Child coroutine 1 completed"
      • 然后启动了一个嵌套的子协程 B:this.launch { delay(2.seconds); println(...) }
      • 注意:B 是在 A 内部启动的,但 launch 是非阻塞的,A 不会等待 B 完成就继续往下执行(实际上 A 已经没有更多代码了)。
  3. 启动第二个子协程
    • this.launch { delay(1.second); println("Child coroutine 2 completed") } 启动了另一个子协程 C。爱吃喝
  4. coroutineScope 等待所有子协程完成
    • coroutineScope 必须等待 A、B、C 全部完成后,才能继续执行后面的 println("Coroutine scope completed")
    • 此时主线程没有被阻塞(因为协程是轻量级的),但控制流被挂起在这里。
  5. 时间线展开
    • t=0s: 打印 "Child coroutine 1 completed"(A 中的第一行代码立刻执行)。
    • t=1s: 协程 C 的 delay(1.second) 结束,打印 "Child coroutine 2 completed",然后 C 完成。
    • t=2s: 协程 B 的 delay(2.seconds) 结束,打印 "Child of the enclosing coroutine completed",然后 B 完成。
    • 此时 A 其实早就完成了(它只有两行代码,第二行是启动 B 而已),B 也完成了,C 也完成了。coroutineScope 的所有子协程都结束了。
  6. 退出 coroutineScope
    • 挂起点恢复,执行 println("Coroutine scope completed")
最终输出顺序:

 

 
Child coroutine 1 completed
Child coroutine 2 completed
Child of the enclosing coroutine completed
Coroutine scope completed

关键点总结:
  • coroutineScope 是一个结构化并发的边界,它保证在其内部启动的所有协程完成后才返回。https://www.ihechi.com
  • launch 启动的协程是并发的,不阻塞父协程的执行,但父作用域会等待它们全部结束。
  • 因此,最后的 println("Coroutine scope completed") 一定是最后执行的,因为它位于 coroutineScope 块之外,且 coroutineScope 本身是挂起函数。

上一篇:在前置条件函数中抛出异常
下一篇:返回列表
关键字:

河池新闻

图说城市 图说天下

阅读排行 阅读排行


爱河池