Kotlin协程GlobalScope.launch与runBlocking的区别

18

这两种方法有什么区别吗?

runBlocking {
   launch(coroutineDispatcher) {
      // job
   }
}
GlobalScope.launch(coroutineDispatcher) {
   // job
}
2个回答

31

runBlocking 函数会运行一个新的协程并阻塞当前线程直到协程完成。这个函数不应该在协程中使用,它被设计用来将常规阻塞代码桥接到以暂停方式编写的库中,在主函数和测试中使用。

// line 1
runBlocking {
   // line 2
   launch(coroutineDispatcher) {
      // line 3
   }
   // line 4
}
// line 5
someFunction()

如果使用runBlocking,那么代码行将按照下一个顺序执行:

line 1
line 2
line 4
line 3
line 5 // this line will be executed after coroutine is finished

全局作用域用于启动在整个应用程序生命周期内运行且不会过早取消的顶级协程。另一个使用全局作用域的地方是在 Dispatchers.Unconfined 中运行的没有任何关联任务的操作符。 应用程序代码通常应该使用应用程序定义的 CoroutineScope,在 GlobalScope 实例上使用 async 或 launch 是极其不鼓励的。

// line 1
GlobalScope.launch(coroutineDispatcher) {
   // line 2
}
// line 3
someFunction()

如果使用GlobalScope.launch,则代码将按照以下顺序执行:

line 1
line 3
line 2

runBlocking 会阻塞当前线程,直到其完成,而 GlobalScope.launch 则不会。


谢谢,但我仍然感到困惑。到处都写着不鼓励使用GlobalScope,但我对我的情况(Spring的PostConstruct,它启动SEDA机制)没有看到任何区别。如果我指定自定义协程调度程序,在我的情况下这两种方法有什么区别? - silent-box
有一个很好的讨论,为什么不建议使用GlobalScope https://dev59.com/9FQJ5IYBdhLWcg3wNjAh。 - Sergio

0

我将尝试用不重复现有标准答案的方式进行不同的解释。

"协程作用域"是协程存在的边界。"全局作用域"存在于应用程序进程运行的同时。如果您使用"GlobalScope.launch()",则会创建一个生存在应用程序作用域中的全局协程。

如果您使用"runBlocking { launch() }",则会创建一个生存在runBlocking之后的局部块中的协程。只要其中的协程仍存活,该局部块就不会退出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接