Kotlin Coroutines - 一个循环内的延迟是如何快速完成的
Kotlin Coroutines - How does a delay within a loop can be completed so fast
我正在尝试 运行 以下代码。
我在控制台中看到创建了大约 8 个工作线程,delayNonBlockingSumOfNumbers()
中 delay
之后的 printThread
方法在不同线程之间并行执行。我无法理解整个操作如何在 1-2 秒内完成。
我相信 1 秒的延迟实际上会应用于某个数字。准确地说,8 个活动线程 运行 并发,因此总延迟时间为 100000 iterations/8 线程 ~ 12500 iterations/thread 或秒。
我的问题是why/how这么快。以及多个延迟块发生了什么,如果不正确,请澄清我的理解。
我看到协程被认为是轻量级线程,
这是否意味着一个线程可以同时处理多个延迟执行?
为什么我这么说是因为,输出显示同一个线程被多次执行,就像这样
如果是这样,我该如何调试或打印 运行 延迟执行的每个挂起块的执行过程,就像我们对线程所做的那样 viz。 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 ")
}
输出:大小为 1_000_000,仅相差 3 秒
查看您的这部分代码:
(1..100000).map {
GlobalScope.async {
//...
}
}
所以您要为 100000 个元素中的每一个元素启动一个新的异步协程。这就是为什么您的延迟不会累积。
how can I debug or print the execution process of each suspended block that runs delaying execution, just like we do for threads viz. Thread.currentThread().name
您所要做的就是启用协程调试模式。根据 documentation,最简单的方法是使用 -ea
JVM 开关。
如果您 运行 以下 -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")
}
}
你应该看到这样的输出:
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
what has happened to multiple delay blocks
你启动了 100,000 个并发协程,所有协程都同时休眠了 1 秒,然后在 1 秒后全部唤醒,完成了你的测试。这与启动 100,000 个线程并让它们休眠所期望的行为完全相同。
就像线程在休眠时不占用CPU核心一样,协程在休眠时也不占用线程。
我正在尝试 运行 以下代码。
我在控制台中看到创建了大约 8 个工作线程,delayNonBlockingSumOfNumbers()
中 delay
之后的 printThread
方法在不同线程之间并行执行。我无法理解整个操作如何在 1-2 秒内完成。
我相信 1 秒的延迟实际上会应用于某个数字。准确地说,8 个活动线程 运行 并发,因此总延迟时间为 100000 iterations/8 线程 ~ 12500 iterations/thread 或秒。
我的问题是why/how这么快。以及多个延迟块发生了什么,如果不正确,请澄清我的理解。
我看到协程被认为是轻量级线程,
这是否意味着一个线程可以同时处理多个延迟执行? 为什么我这么说是因为,输出显示同一个线程被多次执行,就像这样
如果是这样,我该如何调试或打印 运行 延迟执行的每个挂起块的执行过程,就像我们对线程所做的那样 viz。 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 ")
}
输出:大小为 1_000_000,仅相差 3 秒
查看您的这部分代码:
(1..100000).map {
GlobalScope.async {
//...
}
}
所以您要为 100000 个元素中的每一个元素启动一个新的异步协程。这就是为什么您的延迟不会累积。
how can I debug or print the execution process of each suspended block that runs delaying execution, just like we do for threads viz.
Thread.currentThread().name
您所要做的就是启用协程调试模式。根据 documentation,最简单的方法是使用 -ea
JVM 开关。
如果您 运行 以下 -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")
}
}
你应该看到这样的输出:
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
what has happened to multiple delay blocks
你启动了 100,000 个并发协程,所有协程都同时休眠了 1 秒,然后在 1 秒后全部唤醒,完成了你的测试。这与启动 100,000 个线程并让它们休眠所期望的行为完全相同。
就像线程在休眠时不占用CPU核心一样,协程在休眠时也不占用线程。