https://kotlinlang.org logo
#coroutines
Title
# coroutines
a

appasni

02/11/2021, 1:59 PM
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

Niklas Gürtler

02/11/2021, 2:04 PM
There is no guarantee in which order coroutines started by 
launch
 are executed
w

wasyl

02/11/2021, 2:05 PM
t

Timo Gruen

02/11/2021, 2:05 PM
is
launch
itself a suspend function?
🚫 2
n

Niklas Gürtler

02/11/2021, 2:06 PM
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

Timo Gruen

02/11/2021, 2:06 PM
Ah that’s what I was missing. Actually nice to know
a

appasni

02/11/2021, 2:07 PM
But coroutines are sequantial, and coroutines wait for their children to finish
n

Niklas Gürtler

02/11/2021, 2:07 PM
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

appasni

02/11/2021, 2:31 PM
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

Niklas Gürtler

02/11/2021, 2:34 PM
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

Casey Brooks

02/11/2021, 2:46 PM
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

gildor

02/11/2021, 4:14 PM
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

appasni

02/12/2021, 1:45 PM
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

Niklas Gürtler

02/12/2021, 1:47 PM
The IO dispatcher uses multiple threads, so the first launch could happen right away...
a

appasni

02/12/2021, 1:49 PM
Is it specifically because there multiple threads? Isn't it because the thread(s) in IO are different than Main?
n

Niklas Gürtler

02/12/2021, 1:50 PM
Errm right, I misread your message
K 1
👍 1
a

appasni

02/12/2021, 1:51 PM
Thanks, now it's clear. Thank you Niklas for swift responses.
n

Niklas Gürtler

02/12/2021, 1:51 PM
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
5 Views