Android 协同程序的执行顺序是什么?

Android 协同程序的执行顺序是什么?,android,kotlin,coroutine,kotlin-coroutines,Android,Kotlin,Coroutine,Kotlin Coroutines,考虑kotlin中的以下代码 val scope = CoroutineScope(Dispatchers.Main + Job()) scope.launch { println("inside coroutine") } println("outside coroutine") 我们在主(UI)线程中创建了一个协程,并且在该协程之后有一些代码。 我知道在实际代码中这样做没有多大意义,但这只是一个理论问题 考虑到协程在主线程中运行,为什么总是先执行println(“外部协程”) 我本以

考虑kotlin中的以下代码

val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
   println("inside coroutine")
}
println("outside coroutine")
我们在主(UI)线程中创建了一个协程,并且在该协程之后有一些代码。
我知道在实际代码中这样做没有多大意义,但这只是一个理论问题

考虑到协程在主线程中运行,为什么总是先执行println(“外部协程”) 我本以为有时我会首先看到协同程序外部的,而其他时候,首先看到协同程序内部的,有点像两个线程。
谁(操作系统或协同程序实现)决定首先运行协同程序外的coe

考虑到协程在主线程中运行,为什么总是首先执行println(“外部协程”)

让我们假设您的代码是这样的:

someView.post {
   println("inside post")
}
println("outside post")
在这里,我们创建一个
Runnable
(lambda表达式),并将其传递给一些
视图上的
post()
post()
表示
Runnable
将在主应用程序线程上
run()
。。。最终。
Runnable
放在为主应用程序线程供电的
Looper
所使用的工作队列上,当
Runnable
到达队列顶部时执行(或多或少-详细信息比较混乱,但在这里并不重要)

但是,如果在主应用程序线程上执行此代码,
println(“outside post”)
将始终首先打印。
Runnable
被放置到稍后执行的队列中,但您仍在主应用程序线程上执行,因此即使队列为空,
Runnable
也不会运行,直到您将主应用程序线程的控制权返回到Android。因此,在调用
post()
之后,继续执行
println(“外部post”)


在封面下,
Dispatchers.Main
基本上使用的是
post()
(同样,细节更复杂,但对于本次讨论来说并不太重要)。因此,当您
launch()
coroutine时,lambda表达式将排队等待最终在主应用程序上执行。但是,您已经在主应用程序线程上,因此执行将正常继续,并且
println(“outside post”)
将在协同程序有机会执行任何操作之前打印出来

假设您的代码是:

val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
   println("inside coroutine")
}
scope.launch {
   println("inside another coroutine")
}

现在,理论上,这两行中的任何一行都可以先打印出来。您正在对两个lambda表达式进行排队,由调度程序决定在哪个线程的哪个点上运行什么。在实践中,如果总是先打印“内部协同路由”,这并不奇怪,因为
调度器的一个简单实现。Main
将在没有其他约束的情况下使用FIFO排序(例如,协同路由在I/O上被阻塞)。但是,您不应该假定这两个协同路由的调用顺序是特定的

考虑到协程在主线程中运行,为什么总是首先执行println(“外部协程”)

让我们假设您的代码是这样的:

someView.post {
   println("inside post")
}
println("outside post")
在这里,我们创建一个
Runnable
(lambda表达式),并将其传递给一些
视图上的
post()
post()
表示
Runnable
将在主应用程序线程上
run()
。。。最终。
Runnable
放在为主应用程序线程供电的
Looper
所使用的工作队列上,当
Runnable
到达队列顶部时执行(或多或少-详细信息比较混乱,但在这里并不重要)

但是,如果在主应用程序线程上执行此代码,
println(“outside post”)
将始终首先打印。
Runnable
被放置到稍后执行的队列中,但您仍在主应用程序线程上执行,因此即使队列为空,
Runnable
也不会运行,直到您将主应用程序线程的控制权返回到Android。因此,在调用
post()
之后,继续执行
println(“外部post”)


在封面下,
Dispatchers.Main
基本上使用的是
post()
(同样,细节更复杂,但对于本次讨论来说并不太重要)。因此,当您
launch()
coroutine时,lambda表达式将排队等待最终在主应用程序上执行。但是,您已经在主应用程序线程上,因此执行将正常继续,并且
println(“outside post”)
将在协同程序有机会执行任何操作之前打印出来

假设您的代码是:

val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
   println("inside coroutine")
}
scope.launch {
   println("inside another coroutine")
}

现在,理论上,这两行中的任何一行都可以先打印出来。您正在对两个lambda表达式进行排队,由调度程序决定在哪个线程的哪个点上运行什么。在实践中,如果总是先打印“内部协同路由”,这并不奇怪,因为
调度器的一个简单实现。Main
将在没有其他约束的情况下使用FIFO排序(例如,协同路由在I/O上被阻塞)。但是,您不应该假定这两个协同路由的调用顺序是特定的。

Dispatchers.Main
在主循环器上运行。它上面的任何协同程序
launch
都将排队等待执行,因此它将始终稍后运行,因为主循环器将首先执行其他“任务”(生命周期方法、ui回调等)。
Dispatchers.main
在主循环器上运行。任何协同程序
launch
ed都将排队等待执行,因此它将始终稍后运行,因为主循环器将首先执行其他“工作”(生命周期方法、ui回调等)。为了完整性,还有(现在已弃用)选项
CoroutineStart.UNDISPA