println
always prints 3 s regardless of whether I change the values of delay
in the two doXX functions.
Both doXX functions take only 2 seconds, why is the result always 3
I think all three coroutines run concurrently, so I increased the delay in the last coroutine to wait for the first two to finish. Then I print the value of the variable time
.
Here is the code.
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
launch { doSomethingUsefulOne() }
launch { doSomethingUsefulTwo() }
}
launch {
delay(6000)
println("Completed in $time ms")
}
}
suspend fun doSomethingUsefulOne() {
delay(1000L)
}
suspend fun doSomethingUsefulTwo(){
delay(1000L)
}
If I put them in a child scope of the runBlocking scope, the result is always correct. That is about 2 second.
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
doWorld
}
launch {
delay(4000)
println("Completed in $time ms")
}
}
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
launch {
delay(2000L)
println("World 2")
}
launch {
delay(1000L)
println("World 1")
}
println("Hello")
}
CodePudding user response:
Check the docs. The example at the top, which is very similar to yours should clarify this and maybe other aspects of coroutines.
The issue is that launch
launches a new coroutine and continues. The the block after measureTimeMillis
launches 2 coroutines and continues; this takes 3ms to run. The value 3 is stored in time
and that's what the 3rd coroutine prints.
CodePudding user response:
You just discovered a feature of coroutines. They run in parallel. Let us look at the code:
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
launch { doSomethingUsefulOne() } // Launches first coroutine does NOT wait
launch { doSomethingUsefulTwo() } // Launches second coroutine does NOT wait
} // This block is finished in 3ms, because it only launches the coroutines
launch {
delay(6000)
println("Completed in $time ms")
}
}
If you want to wait for both of the coroutines to finish you can wrap them in coroutineScope
or runBlocking
:
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
runBlocking { // waits for all contained coroutines to finish
launch { doSomethingUsefulOne() } // Launches first coroutine does NOT wait
launch { doSomethingUsefulTwo() } // Launches second coroutine does NOT wait
}
}
launch {
delay(6000)
println("Completed in $time ms")
}
}