I am trying to understand coroutines in Kotlin, but I've hit a bit of a roadblock. In the following example I would expect the following to happen:
But it prints this:
0
3
2
1
4
5
6
I don't really understand why this is happening. I mostly don't understand how the output of job2
can come before 4
. I am very confused.
println("0")
runBlocking {
val job = GlobalScope.launch {
// launch new coroutine and keep a reference to its Job
delay(1200L)
println("1")
}
val job2 = GlobalScope.launch {
// launch new coroutine and keep a reference to its Job
delay(1000L)
println("2")
}
println("3")
job.join() // wait until child coroutine completes
println("4")
job2.join() // wait until child coroutine
println("5")
}
println("6")
Reading from the documentation of kotlinx.coroutines#launch:
By default, the coroutine is immediately scheduled for execution. Other start options can be specified via start parameter. See CoroutineStart for details. An optional start parameter can be set to CoroutineStart.LAZY to start coroutine lazily. In this case, the coroutine Job is created in new state. It can be explicitly started with start function and will be started implicitly on the first invocation of join.
So your coroutine starts immediate after the launch
command. This should explain the order of executed commands. The delay
in your async coroutines is executed right away while the main thread executes the next statements. 3
before 2
before 1
. Then you wait until your first job is finished (printing 1
) before printing 4
from the main thread.
If you want your code to be executed like you expect it, you can add the start = CoroutineStart.LAZY
parameter to the launch
like this:
println("0")
runBlocking {
val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
// launch new coroutine and keep a reference to its Job
delay(1200L)
println("1")
}
val job2 = GlobalScope.launch(start = CoroutineStart.LAZY) {
// launch new coroutine and keep a reference to its Job
delay(1000L)
println("2")
}
println("3")
job.join() // wait until child coroutine completes
println("4")
job2.join() // wait until child coroutine
println("5")
}
println("6")