协程的执行顺序是什么?
What is the order of execution with coroutines?
在 kotlin 中考虑以下代码。
val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
println("inside coroutine")
}
println("outside coroutine")
我们在Main(UI)线程中创建一个协程,协程后面有一些代码。
我知道在实际代码中这样做没有多大意义,但这只是一个理论问题。
考虑到Main线程中的协程运行,为什么println("outside coroutine")是总是先执行?
我本以为有时我会先看到 outside coroutine 而其他时候,我会先看到 inside coroutine,有点像两个线程。
谁(OS or Coroutines实现)决定协程外的coe先运行?
Considering that the coroutine runs in the Main thread, why println("outside coroutine") is ALWAYS executed first?
让我们假设您的代码是这样的:
someView.post {
println("inside post")
}
println("outside post")
在这里,我们创建了一个 Runnable
(lambda 表达式)并将其传递给某些 View
上的 post()
。 post()
表示 Runnable
将在主应用程序线程上 run()
......最终。 Runnable
被放入为主应用程序线程供电的 Looper
使用的工作队列中,并在 Runnable
到达队列顶部时执行(或多或少 - IIRC 的细节比较混乱,但在这里并不重要)。
但是如果您在主应用程序线程上执行此代码,println("outside post")
将始终首先打印。 Runnable
被放置到队列中稍后执行,但您仍在主应用程序线程上执行,因此即使队列为空,Runnable
也不会 运行 直到您 return 将主应用程序线程的控制权交还给 Android。因此,在调用 post()
之后,继续执行 println("outside post")
.
在幕后,Dispatchers.Main
基本上是在使用 post()
(同样,细节更复杂,但对于本次讨论来说不是太重要)。因此,当您 launch()
协程时,该 lambda 表达式会排队等待最终在主应用程序上执行。但是,您已经在主应用程序线程上,因此执行正常继续,并且 println("outside post")
在协程有机会做任何事情之前被打印出来。
假设您的代码是:
val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
println("inside coroutine")
}
scope.launch {
println("inside another coroutine")
}
现在您所处的情况是,理论上可以先打印这两行中的任何一行。您正在排队两个 lambda 表达式,由调度程序决定在什么时候在什么线程上 运行 什么。在实践中,如果 "inside coroutine" 总是首先打印,我不会感到惊讶,因为 Dispatchers.Main
的简单实现将在没有其他约束的情况下使用 FIFO 排序(例如,协程在 [=45 上被阻塞) =]).但是,您不应该假设这两个协程的调用顺序是特定的。
在 kotlin 中考虑以下代码。
val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
println("inside coroutine")
}
println("outside coroutine")
我们在Main(UI)线程中创建一个协程,协程后面有一些代码。
我知道在实际代码中这样做没有多大意义,但这只是一个理论问题。
考虑到Main线程中的协程运行,为什么println("outside coroutine")是总是先执行?
我本以为有时我会先看到 outside coroutine 而其他时候,我会先看到 inside coroutine,有点像两个线程。
谁(OS or Coroutines实现)决定协程外的coe先运行?
Considering that the coroutine runs in the Main thread, why println("outside coroutine") is ALWAYS executed first?
让我们假设您的代码是这样的:
someView.post {
println("inside post")
}
println("outside post")
在这里,我们创建了一个 Runnable
(lambda 表达式)并将其传递给某些 View
上的 post()
。 post()
表示 Runnable
将在主应用程序线程上 run()
......最终。 Runnable
被放入为主应用程序线程供电的 Looper
使用的工作队列中,并在 Runnable
到达队列顶部时执行(或多或少 - IIRC 的细节比较混乱,但在这里并不重要)。
但是如果您在主应用程序线程上执行此代码,println("outside post")
将始终首先打印。 Runnable
被放置到队列中稍后执行,但您仍在主应用程序线程上执行,因此即使队列为空,Runnable
也不会 运行 直到您 return 将主应用程序线程的控制权交还给 Android。因此,在调用 post()
之后,继续执行 println("outside post")
.
在幕后,Dispatchers.Main
基本上是在使用 post()
(同样,细节更复杂,但对于本次讨论来说不是太重要)。因此,当您 launch()
协程时,该 lambda 表达式会排队等待最终在主应用程序上执行。但是,您已经在主应用程序线程上,因此执行正常继续,并且 println("outside post")
在协程有机会做任何事情之前被打印出来。
假设您的代码是:
val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
println("inside coroutine")
}
scope.launch {
println("inside another coroutine")
}
现在您所处的情况是,理论上可以先打印这两行中的任何一行。您正在排队两个 lambda 表达式,由调度程序决定在什么时候在什么线程上 运行 什么。在实践中,如果 "inside coroutine" 总是首先打印,我不会感到惊讶,因为 Dispatchers.Main
的简单实现将在没有其他约束的情况下使用 FIFO 排序(例如,协程在 [=45 上被阻塞) =]).但是,您不应该假设这两个协程的调用顺序是特定的。