在kotlin中考虑以下代码。
val scope = CoroutineScope(Dispatchers.Main + Job())
scope.launch {
println("inside coroutine")
}
println("outside coroutine")
我们在Main(UI)线程中创建一个协程,协程后有一些代码。
我知道在实际代码中这样做没有多大意义,但这只是一个理论问题。
考虑到协程在主线程中运行,为什么总是首先执行 println(“ outside coroutine”) ?
我原本希望有时候我会先看到 协程外 ,而有时会看到第一个 协程内 ,就像两个线程。
谁(操作系统或协同程序实现)决定首先运行协同程序外部的coe?
答案 0 :(得分:1)
考虑到协程在主线程中运行,为什么总是先执行println(“ outside coroutine”)?
让我们想象您的代码是这样的:
someView.post {
println("inside post")
}
println("outside post")
在这里,我们创建一个Runnable
(lambda表达式),并将其传递给某些post()
上的View
。 post()
表示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上被阻塞) 。但是,您不应该假定这两个协程的特定调用顺序。