```fun main(): Unit = runBlocking { println(1)...
# coroutines
a
Copy code
fun main(): Unit = runBlocking {
    println(1)
    launch {
        println(2)
        launch {
            println(3)
        }
    }
    launch {
        println(4)
    }
    println(5)
}
why does the above code print 1 5 2 4 3 instead of 1 2 3 4 5 everything is running in main thread?
n
There is no guarantee in which order coroutines started by 
launch
 are executed
w
t
is
launch
itself a suspend function?
🚫 2
n
Seems like kotlin runs the code until a suspension point - here the end of the runBlocking block - printing 1 5 2, and then begins executing the first coroutine that was launched, which prints 2, ...
no, launch returns immediately
t
Ah that’s what I was missing. Actually nice to know
a
But coroutines are sequantial, and coroutines wait for their children to finish
n
It does, after printing 5 and before runBlocking returns
if you want to launch a child and then directly wait for it - why launch a child at all, instead of running the code directly? perhaps you just need runBlocking or coroutineScope or withContext
a
It looks like outermost coroutines are executed before any coroutines that are one level below regardless of whether the lower coroutines have separate parent coroutines, is my conclusion correct?
n
Order is not guaranteed for this case, so it's best not to assume anything and only use constructs with guaranteed order
👍 1
If you run the child with coroutineScope or async+await, it will be executed first
c
launch
is for starting coroutines that run in parallel. Depending on the Dispatcher, they may run on different threads, but even on a single-threaded Dispatcher the order is not guaranteed. You can think of each
launch { }
as adding that block to an event queue, and whenever a thread is available to run the next job, it takes from the head of the queue. So in this example it works like this: 1.
println(1)
runs immediately and you get 1 printed 2. The first
launch { }
is added to the end of the queu, but the
runBlocking
block is still running so it does not execute yet 3. LIkewise, the second
launch { }
block is added to the queue, after the first 4.
println(5)
is now run and 5 gets printed 5. Now that the first job is finished, the next job is taken from the queue. This is the first
launch
, so we get
println(2)
run and 2 is printed. 6. Still inside the first
launch
, the nested
launch
is added to the end of the queue (which is ordered after the second
launch
block) 7. The first
launch
has completed, so the next job to run is the second launch block, and
println(4)
is executed 8. Finally, the last job from the nested
launch
is run and
println(3)
is executed
❤️ 2
☝️ 3
g
Great explanation from Casey, I would also add if you replace println with some suspend function which awaits something asynchronously, order can be completely different, just because launch is a separate job, in your example they do not wait each other, just run concurrently even on a single threaded dispatcher
a
I specified IO dispatcher in the first launch builder, the result was, 1, 2, 3, 5, 4. Looks like when a coroutine is started with the same context/dispatcher the code inside the coroutine executes only when the thread becomes available. Since after the first launch there was still code to execute on the thread (the last launch + println(5)). After println(5) is executed the thread becomes available for the launched coroutines.
n
The IO dispatcher uses multiple threads, so the first launch could happen right away...
a
Is it specifically because there multiple threads? Isn't it because the thread(s) in IO are different than Main?
n
Errm right, I misread your message
K 1
👍 1
a
Thanks, now it's clear. Thank you Niklas for swift responses.
n
But better not rely on that! The execution order is still up to the environment. The result "1 2 3 5 4" is still random and not guaranteed
👍 1
☝️ 1