joinAll() 在语义上等同于按顺序调用 join() 是什么意思?

huangapple go评论74阅读模式
英文:

What does Kotlin coroutines documentation mean when they say joinAll() is semantically equivalent to calling join() in sequence?

问题

https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/join-all.html 中指出:“该方法在语义上等同于使用 forEach { it.join() } 逐个加入所有给定的作业。”

我有这段代码

import kotlinx.coroutines.*

fun main() {
  joinTest()
  joinAllTest()
}

fun joinAllTest() {
  val begin = System.currentTimeMillis()
  runBlocking { (0..2).map { launch { delay1s(it) } }.joinAll() }
  val end = System.currentTimeMillis()

  println("joinAllTest took: ${end-begin}")
}

fun joinTest() {
  val begin = System.currentTimeMillis()
  runBlocking {
    for (i in 0..2) {
      val job2 = launch { delay1s(i) }
      job2.join()
    }
  }
  val end = System.currentTimeMillis()

  println("joinTest took: ${end-begin}")
}

suspend fun delay1s(i: Int) {
  delay(1000)
}

这会产生以下结果:

joinTest took: 3101
joinAllTest took: 1011

如何使 join() 在语义上等同于具有以下行为的 joinAll()?调用 join() 会逐个挂起在每个加入上,而 joinAll() 会并行运行它们。

英文:

In https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/join-all.html it's stated that "This method is semantically equivalent to joining all given jobs one by one with forEach { it.join() }."

I have this code

import kotlinx.coroutines.*

fun main() {
  joinTest()
  joinAllTest()
}

fun joinAllTest() {
  val begin = System.currentTimeMillis()
  runBlocking { (0..2).map { launch { delay1s(it) } }.joinAll() }
  val end = System.currentTimeMillis()

  println("joinAllTest took: ${end-begin}")
}

fun joinTest() {
  val begin = System.currentTimeMillis()
  runBlocking {
    for (i in 0..2) {
      val job2 = launch { delay1s(i) }
      job2.join()
    }
  }
  val end = System.currentTimeMillis()

  println("joinTest took: ${end-begin}")
}


suspend fun delay1s(i: Int) {
  delay(1000)
}

This produces:

joinTest took: 3101
joinAllTest took: 1011

How can join() be semantically equivalent to joinAll() with the following behavior? Calling join sequentially suspends on each join while joinAll() runs them in parallel.

答案1

得分: 2

The relevant source code in kotlinx.coroutines is as follows:

public suspend fun Collection<Job>.joinAll(): Unit = forEach { it.join() }

The implementation indicates that the joinAll function is equivalent to forEach { it.join() }.

英文:

Relevant source code in kotlinx.coroutines

public suspend fun Collection&lt;Job&gt;.joinAll(): Unit = forEach { it.join() }

The implementation tells us that the joinAll function is literally equal to forEach { it.join() }

The reason for the different timings of your functions is that in the first case, the delays are performed in parallel, and in the second, each subsequent one waits for the previous one to complete.

So in your case joinTest should be:

fun joinTest() {
  val begin = System.currentTimeMillis()
  runBlocking { (0..2).map { launch { delay1s(it) } }.forEach{it.join()} }
  val end = System.currentTimeMillis()

  println(&quot;joinTest took: ${end-begin}&quot;)
}

huangapple
  • 本文由 发表于 2023年6月6日 02:15:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76409012.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定