协程的执行顺序是什么?

时间:2019-10-17 23:32:53

标签: android kotlin coroutine kotlin-coroutines

在kotlin中考虑以下代码。

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

我们在Main(UI)线程中创建一个协程,协程后有一些代码。
我知道在实际代码中这样做没有多大意义,但这只是一个理论问题。

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

1 个答案:

答案 0 :(得分:1)

  

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

让我们想象您的代码是这样的:

someView.post {
   println("inside post")
}
println("outside post")

在这里,我们创建一个Runnable(lambda表达式),并将其传递给某些post()上的Viewpost()表示Runnable将在主应用程序线程上成为run(),最终。将Runnable放在驱动主应用程序线程的Looper使用的工作队列上,并且当Runnable到达队列的顶部(或多或少-详细信息使IIRC更加混乱,但在这里并不重要)。

但是,如果您在主应用程序线程上执行此代码,将始终首先打印println("outside post")Runnable放在队列中以待稍后执行,但是您仍在主应用程序线程上执行,因此即使队列为空,在您返回对{主应用程序线程返回到Android。因此,在调用Runnable之后,执行将继续post()

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

假设您的代码是:

println("outside post")

现在您处于理论上可以先打印其中任何一行的情况。您要同时排队两个lambda表达式,然后由调度程序决定在什么时候在什么线程上运行什么。实际上,如果始终先打印“内部协程”,这不会令我感到惊讶,因为val scope = CoroutineScope(Dispatchers.Main + Job()) scope.launch { println("inside coroutine") } scope.launch { println("inside another coroutine") } 的简单实现将在没有其他约束的情况下使用FIFO排序(例如,协程在I / O上被阻塞) 。但是,您不应该假定这两个协程的特定调用顺序。