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

预期结果应如下所示,因为async-block#2首先到达/获取singleThread



但实际结果是



single-thread-block-#2和single-thread-block-#1似乎可以并行运行,singleThread在这里没有什么不同

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) {..}使用的线程)并不忙于等待时间的流逝。

整体情况看起来像这样

  • ...
  • “异步块#2”打印
  • 任务2在singleThread
  • 上运行
  • 任务2已被delay(1500)暂停,singleThread是免费的
  • 任务1在singleThread
  • 上启动
  • 任务1已被delay(500)暂停,singleThread是免费的
  • 在这一点上,我们有延迟队列:
  • 恢复任务1的delay(500)
  • 恢复任务2的delay(1500)
  • 一段时间后
  • resume(500)安排任务1的第二部分在singleThread中运行
  • 一段时间后
  • resume(1500)安排任务2的第二部分在singleThread中运行
  • 10-04 13:59