协程的执行顺序无法预测?

时间:2018-11-29 19:39:53

标签: kotlin kotlinx.coroutines

这就是我的想法: 使用协程时,您要堆积异步操作,一旦完成同步操作,就以FIFO顺序调用它们。但这并不总是正确的

在此示例中,您得到了我所期望的:

fun main() = runBlocking {
   launch {
      println("1")
   }

   launch {
      println("2")
   }

   println("0")
}

也在这里(带有嵌套启动):

fun main() = runBlocking {
   launch {
      println("1")
   }

   launch {
      launch {
         println("3")
      }

      println("2")
   }

   println("0")
}

在此示例中,现在使用范围生成器并创建另一个“堆”(不是真实术语),顺序会发生变化,但是您仍然可以按预期得到

fun main() = runBlocking {
   launch {
      println("2")
   }

   // replacing launch
   coroutineScope {
      println("0")
   }

   println("1")
}

最后..这个问题的原因..带有作用域生成器的示例2:

fun main() = runBlocking {
   launch {
      println("3")
   }

   coroutineScope {
      launch {
         println("1")
      }

      println("0")
   }

   println("2")
}

我明白了:     0     3     1个     2

为什么?

如果我的假设是错误的,那不是协程的工作方式

如果是这样,那么编码时我应该如何确定正确的顺序

编辑:我曾尝试在不同的机器和不同的平台上运行相同的代码,但总是得到相同的结果。.还尝试了更复杂的嵌套以证明结果的不变性

在查阅文档时发现协程只是代码转换(正如我最初所想的那样)

请记住,即使喜欢将它们称为“轻量级”线程,它们也会在单个“真实”线程中运行(注意:没有newSingleThreadContext)

因此,我选择相信执行顺序是在编译时预先确定的,而不是在运行时确定的

毕竟..我仍然无法预期订单..那就是我想要的

1 个答案:

答案 0 :(得分:0)

不要假设协程将以特定顺序运行,运行时将决定什么时间和顺序运行最佳。您可能对此有帮助的是kotlinx.coroutines documentation。它在解释它们如何工作方面做得很出色,还提供了一些方便的抽象来帮助管理协程更加有意义。我个人建议检查channelsjobsDeferred (async/await)

例如,如果我希望事情按编号顺序完成,那么我会使用渠道来确保事情按我想要的顺序到达。

runBlocking {
    val channel = Channel<Int>()
    launch {
        for (x in 0..5) channel.send(x * x)
        channel.close()
    }

    for (msg in channel) {
        // Pretend we're doing some work with channel results
        println("Message: $msg")
    }
}

希望可以为您提供更多背景信息或协程是什么以及它们的优点。