Kotlin 协程:在单线程中一次一个协程

Kotlin Coroutines: one single coroutine at a time in single thread

考虑下面的代码,我正在尝试使用 Executors.newFixedThreadPool(1).asCoroutineDispatcher() 创建单线程调度程序;我希望 launch(singleThread){...} 中的代码按顺序执行

预期结果应该如下所示,因为 async-block#2 reach/acquire singleThread first

async block #2
async block #1
single thread block #2
single thread block #1
The answer is 3

但实际结果是

async block #2
async block #1
single thread block #1
single thread block #2
The answer is 3

single-thread-block-#2 和 single-thread-block-#1 似乎 运行 并行,singleThread 在这里没有区别 </p> <pre><code>import java.util.concurrent.Executors import kotlinx.coroutines.* import kotlin.system.* val singleThread = Executors.newFixedThreadPool(1).asCoroutineDispatcher() fun main() = runBlocking<Unit> { val time = measureTimeMillis { val one = async { // async block #1 delay(200) println("async block #1") launch (singleThread) { delay(500) println("single thread block #1") } 2 } val two = async { // async block #2 delay(100) println("async block #2") launch (singleThread) { delay(1500) println("single thread block #2") } 1 } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") }

注意 delay() 是代码中的 suspend 函数。它是通过协程挂起实现的。这意味着代码的执行在您调用 delay 的那一刻暂停,只有在超时后才恢复。线程(例如,您通过 async(singleThread) {..} 使用的线程不忙,等待时间结束。

总体情况是这样的

  • ...
  • "async block #2" 印刷
  • 任务 2 运行宁 singleThread
  • 任务 2 暂停 delay(1500)singleThread 空闲
  • 任务 1 在 singleThread
  • 开始
  • 任务 1 暂停 delay(500)singleThread 空闲
  • 那时我们有延迟队列:
    • 恢复任务 1delay(500)
    • 恢复任务 2delay(1500)
  • 一段时间后
  • resume(500) 将任务 1 的第二部分安排到 singleThread
  • 中的 运行
  • 一段时间后
  • resume(1500) 将任务 2 的第二部分安排到 singleThread
  • 中的 运行

除了@EugenePetrenko 的回答之外,还有一个新方法 CoroutineDispatcher.limitedParallelism(numberOfParallelism),您可以使用它来保证并行性限制 - 在此调度程序中最多可以并发执行 1 个协程。它看起来像:

val singleThread = Dispatchers.IO.limitedParallelism(1)

someCoroutineScope.launch (singleThread) {
    ...
}

函数 limitedParallelismkotlinx.coroutines 库的 1.6.0 版本开始可用。