为什么这些协程不能提供预期的输出?

时间:2018-12-05 15:22:06

标签: kotlin kotlinx.coroutines

我试图了解Kotlin中的协程,但遇到了一些障碍。在下面的示例中,我希望发生以下情况:

  • 打印0
  • 设置作业1
  • 设置作业2
  • 打印3张
  • 运行作业1
  • 等待1.2秒
  • 打印1
  • 打印4张
  • 运行作业2
  • 等待1秒
  • 打印2
  • 打印5张
  • 打印6

但是它打印出:

0
3
2
1
4
5
6

我真的不明白为什么会这样。我大多不了解job2的输出会比4早。我很困惑。

println("0")
runBlocking {
    val job = GlobalScope.launch {
        // launch new coroutine and keep a reference to its Job
        delay(1200L)
        println("1")
    }
    val job2 = GlobalScope.launch {
        // launch new coroutine and keep a reference to its Job
        delay(1000L)
        println("2")
    }

    println("3")
    job.join() // wait until child coroutine completes
    println("4")
    job2.join() // wait until child coroutine
    println("5")
}
println("6")

2 个答案:

答案 0 :(得分:3)

documentation of kotlinx.coroutines#launch中读取内容:

  

默认情况下,协程将立即安排执行。其他启动选项可以通过启动参数指定。有关详细信息,请参见CoroutineStart。可以将可选的启动参数设置为CoroutineStart.LAZY以延迟启动协程。在这种情况下,协程作业将以新状态创建。可以使用start函数显式启动它,并将在首次调用join时隐式启动。

因此,您的协程在launch命令之后立即开始。这应该说明已执行命令的顺序。异步协程中的delay立即执行,而主线程执行下一条语句。 {{1}之前的3之前的2。然后,您要等到第一项工作完成(打印1)之后,再从主线程打印1

如果您希望按期望的方式执行代码,可以将4参数添加到start = CoroutineStart.LAZY中,如下所示:

launch

答案 1 :(得分:3)

会发生什么:

  1. 打印0
  2. 输入runBlocking,它将阻塞当前线程,直到阻塞完成。
  3. 设置和launch job 1;作业立即开始执行,并由delay语句暂停1200ms。
  4. 设置和启动job2;作业立即开始执行,并通过延迟语句暂停执行1000m。
  5. 打印3
  6. 等待(执行暂停),直到作业1完成(job.join())。
  7. 作业1000 ms后2 打印2 并完成
  8. 作业1200毫秒后打印1 并完成
  9. 打印4 (因为作业1已完成)
  10. 等待(执行暂停),直到job2完成(job2.join())。立即返回,因为job2已经完成。
  11. 打印5
  12. runBlocking块完成后,
  13. 打印6 ,并且继续从其开始的线程。

您可以阅读https://kotlinlang.org/docs/reference/coroutines/composing-suspending-functions.html,以更好地了解暂停功能。这段视频帮助我了解了协程:https://www.youtube.com/watch?v=_hfBv0a09Jc