gpt4 book ai didi

kotlin - 使用 launch 启动协程或使用 coroutineScope 启动协程之间的区别

转载 作者:行者123 更新时间:2023-12-02 18:01:30 38 4
gpt4 key购买 nike

看来我可以使用多种机制来启动协程。其中两个是 coroutineScopelaunch 但是阅读 Kotlin coroutine 文档我不清楚有什么区别以及我什么时候会使用一个而不是另一个

fun main() {
println("Main block ${Thread.currentThread().name}")
runBlocking {
coroutineScope {
println("Coroutine scope ${Thread.currentThread().name}")
}
launch {
println("Launch ${Thread.currentThread().name}")
}
}
}

我运行了上面的代码,可以看到两者都启动了一个新的协程。有什么区别?

最佳答案

CoroutineScope 是一种组织性的东西 - 它可以让您将协程组合在一起以执行 structured concurrency .基本上,它允许您控制范围内所有内容(包括在其他协程中启动的协程)的生命周期,并处理诸如传播结果和错误以及取消范围内的所有内容之类的事情。 More info here

所有协程构建器函数(包括launch)在 CoroutineScope(或它作为接收器,如果你想那样看的话):

fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job

因此,您示例中的launch 调用正在当前CoroutineScope 中运行,它由runBlocking builder 提供。 :

expect fun <T> runBlocking(
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> T
): T

看看你传递的 lambda 实际上是一个 CoroutineScope.() -> T?它以 CoroutineScope 作为接收器运行 - 这就是您调用 launch 的地方。你不能从任何地方调用它!

因此,当您在您的示例中创建一个 CoroutineScope 时,您将在 这个 CoroutineScope 中嵌套一个 runBlocking 正在提供。 runBlocking 将不允许其后的其余代码继续(即它阻止执行),直到其 CoroutineScope 中的所有内容都已完成。在里面创建你自己的 CoroutineScope 可以让你定义一个你可以控制的协程子集 - 你可以 cancel 它们,但是如果 中还有其他协程在运行runBlocking 作用域,它将一直阻塞直到它们也完成。


就像 Louis 在另一个答案中所说的那样,您实际上并没有在您创建的范围内创建任何协程。代码只是在 runBlocking 开始运行您传递的代码块的协程中运行。检查一下:

fun main() {
println("Main")
runBlocking {
coroutineScope {
delay(1000)
println("I'm in a coroutine scope")
}
launch {
delay(500)
println("First new coroutine")
}
launch {
delay(50)
println("Second new coroutine")
}
}
}
Main
I'm in a coroutine scope
Second new coroutine
First new coroutine

单个协程中的代码按顺序执行 - 所以会发生什么

  • 你从主线开始
  • 您输入 runBlocking block 的协程
  • 您创建一个CoroutineScope,它只会影响您在其上启动(等)的东西
  • 你延迟,然后打印一行
  • 您点击了第一个 launch 并创建了一个新协程。这从延迟 500 毫秒开始,但它现在独立运行 - 不同的协程同时运行
  • 您移至下一行,启动第二个协程。它也自己运行,并立即延迟 50 毫秒。现在有3个协程在运行
  • 您已完成 block 中的代码 - 此协程已完成。 但是,还有两个正在运行的协程也在这个 CoroutineScope 上启动,所以 runBlocking 等待它们完成。
  • 延迟最短的第二个协程先打印,然后完成
  • 第一个协程最后完成,因为即使它启动得更早,它们都是独立运行的
  • 现在 runBlocking CoroutineScope 中的所有内容都已完成,它可以完成并允许在 main() 中继续执行

如果您在您创建的范围内启动一个协程,它将以相同的方式工作——只是您可以对其中的内容进行细粒度控制,特别是您可以专门与嵌套范围内的协程一起工作,而不会影响外部范围内的事物。重要的是一旦内部作用域完成,它就可以通知外部作用域一切都完成了,诸如此类的事情

关于kotlin - 使用 launch 启动协程或使用 coroutineScope 启动协程之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74268483/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com