Kotlin 协程 - 循环内的延迟如何能够如此快地完成

abi*_*ode 5 performance kotlin kotlin-coroutines

我正在尝试运行以下代码。

我在控制台中看到大约创建了 8 个工作线程,并且inprintThread之后的方法在不同线程之间并行执行。我无法理解整个操作如何在 1-2 秒内完成。delaydelayNonBlockingSumOfNumbers()

我相信 1 秒的延迟实际上会应用于某个数字。准确地说,8 个活动线程同时运行,因此总延迟时间将为 100000 次迭代/8 个线程 ~ 12500 次迭代/线程或秒。

我的问题是为什么/怎么这么快。还有多个延迟块发生了什么,如果不正确,请澄清我的理解。

我看到协程被认为是轻量级线程,

这是否意味着一个线程可以同时处理多个延迟执行? 为什么我这么说是因为,输出显示同一个线程正在执行中多次使用,如下所示

协程在循环中执行输出

如果是这样,我如何调试或打印每个运行延迟执行的挂起块的执行过程,就像我们对线程所做的那样。Thread.currentThread().name

如果我使用 Thread.sleep(1000) 而不是延迟,并打印线程,则输出将显示每次执行之间有 1 秒的差异。同样,我应该如何显示协程执行的类似输出,以便我可以看到正在处理的实际延迟?

fun delayNonBlockingSumOfNumbers(){

  printThread("Start of delayNonBlockingSumOfNumbers()")
  val deferredList = (1..100000).map {
    GlobalScope.async {
        //printThread("In Async Before Index $it")
        val timetaken:Long = 1000
        delay(timetaken)
        printThread("In Async After Delay Index $it time is -> $timetaken")
        it
    }
  }
 runBlocking {
    val sum = deferredList.sumBy { it.await() }
    printThread("End of delayNonBlockingSumOfNumbers(), sum = $sum")
 }
}

fun printThread(message:String){
  println("$message ${Thread.currentThread().name} ${Instant.now()}")
}

fun main(){
 delayNonBlockingSumOfNumbers()
 Thread.sleep(20_000)
 printThread("End of ")
}
Run Code Online (Sandbox Code Playgroud)

输出:大小为 1_000_000,仅相差 3 秒

1_000_000 协程示例

Mar*_*nik 5

如何调试或打印每个运行延迟执行的挂起块的执行过程,就像我们对线程所做的那样。Thread.currentThread().name

您所要做的就是启用协程调试模式。根据文档,最简单的方法是使用-eaJVM 开关。

如果您运行以下命令-ea

fun main() {
    measureTimeMillis {
        runBlocking {
            (1..4).forEach {
                launch {
                    println("$it, delaying in ${Thread.currentThread().name}")
                    delay(1000)
                    println("$it, done in ${Thread.currentThread().name}")
                }
            }
        }
    }.also {
        println("Took $it ms")
    }
}
Run Code Online (Sandbox Code Playgroud)

你应该看到这样的输出:

1, delaying in main @coroutine#2
2, delaying in main @coroutine#3
3, delaying in main @coroutine#4
4, delaying in main @coroutine#5
1, done in main @coroutine#2
2, done in main @coroutine#3
3, done in main @coroutine#4
4, done in main @coroutine#5
Took 1099 ms
Run Code Online (Sandbox Code Playgroud)

多个延迟块发生了什么

你启动了 100,000 个并发协程,所有协程同时休眠 1 秒,然后 1 秒后全部醒来,完成你的测试。这与启动 100,000 个线程并使它们休眠时所期望的行为完全相同。

就像线程在睡眠时不占用 CPU 核心一样,协程在睡眠时也不占用线程。