bschandramohan
bschandramohan

Reputation: 2006

Kotlin Coroutine Launch inside another launch getting called sequentially

I have 2 suspend methods invoked via launch and both of those methods creates further coroutines via launch. I see the results are sequential. If I remove the second level launch, then I see that the operations are executed in parallel. Can someone throw light on why this isn't being run in async/parallel?


private suspend fun coroutineA() = coroutineScope {
    println("[${printThreadInfo()}] Starting coroutineA()")
    (1..10).forEach {
        launch {
            delay(1000)
            println("[${printThreadInfo()}] A$it")
        }
    }
}

private suspend fun coroutineB() = coroutineScope {
    println("[${printThreadInfo()}] Starting coroutineB()")
    (1..10).forEach {
        launch {
            delay(1000)
            println("[${printThreadInfo()}] B$it")
        }
    }
}


// -Dkotlinx.coroutines.debug
fun main() {
    runBlocking {
        launch {
            println("[${printThreadInfo()}] Launching coroutineA")
            coroutineA()
        }
        launch {
            println("[${printThreadInfo()}] Launching coroutineB")
            coroutineB()
        }
    }
}

The result I see is:

[2020-11-20T07:53:17.749 Thread=main] Start of main()
[2020-11-20T07:53:17.859 Thread=main @coroutine#1] Launching launchMultipleCoroutines
[2020-11-20T07:53:17.866 Thread=main @coroutine#2] Launching coroutineA
[2020-11-20T07:53:17.868 Thread=main @coroutine#2] Starting coroutineA()
[2020-11-20T07:53:17.871 Thread=main @coroutine#3] Launching coroutineB
[2020-11-20T07:53:17.872 Thread=main @coroutine#3] Starting coroutineB()
[2020-11-20T07:53:18.878 Thread=main @coroutine#4] A1
[2020-11-20T07:53:18.878 Thread=main @coroutine#5] A2
[2020-11-20T07:53:18.878 Thread=main @coroutine#6] A3
[2020-11-20T07:53:18.879 Thread=main @coroutine#7] A4
[2020-11-20T07:53:18.879 Thread=main @coroutine#8] A5
[2020-11-20T07:53:18.879 Thread=main @coroutine#9] A6
[2020-11-20T07:53:18.879 Thread=main @coroutine#10] A7
[2020-11-20T07:53:18.879 Thread=main @coroutine#11] A8
[2020-11-20T07:53:18.880 Thread=main @coroutine#12] A9
[2020-11-20T07:53:18.880 Thread=main @coroutine#13] A10
[2020-11-20T07:53:18.880 Thread=main @coroutine#14] B1
[2020-11-20T07:53:18.880 Thread=main @coroutine#15] B2
[2020-11-20T07:53:18.880 Thread=main @coroutine#16] B3
[2020-11-20T07:53:18.880 Thread=main @coroutine#17] B4
[2020-11-20T07:53:18.881 Thread=main @coroutine#18] B5
[2020-11-20T07:53:18.881 Thread=main @coroutine#19] B6
[2020-11-20T07:53:18.881 Thread=main @coroutine#20] B7
[2020-11-20T07:53:18.881 Thread=main @coroutine#21] B8
[2020-11-20T07:53:18.881 Thread=main @coroutine#22] B9
[2020-11-20T07:53:18.881 Thread=main @coroutine#23] B10

whereas if I remove the launch() inside coroutineA and coroutineB, I see that the results looks like executed in parallel:

[2020-11-20T08:02:49.356 Thread=main @coroutine#2] Launching coroutineA
[2020-11-20T08:02:49.407 Thread=main @coroutine#2] Starting coroutineA()
[2020-11-20T08:02:49.415 Thread=main @coroutine#3] Launching coroutineB
[2020-11-20T08:02:49.415 Thread=main @coroutine#3] Starting coroutineB()
[2020-11-20T08:02:49.512 Thread=main @coroutine#2] A1
[2020-11-20T08:02:49.516 Thread=main @coroutine#3] B1
[2020-11-20T08:02:49.612 Thread=main @coroutine#2] A2
[2020-11-20T08:02:49.617 Thread=main @coroutine#3] B2
[2020-11-20T08:02:49.716 Thread=main @coroutine#2] A3
[2020-11-20T08:02:49.718 Thread=main @coroutine#3] B3
[2020-11-20T08:02:49.817 Thread=main @coroutine#2] A4
[2020-11-20T08:02:49.819 Thread=main @coroutine#3] B4
[2020-11-20T08:02:49.921 Thread=main @coroutine#2] A5
...

Upvotes: 1

Views: 2288

Answers (1)

bschandramohan
bschandramohan

Reputation: 2006

Figured out that we need to use launch(Dispatchers.Default) to achieve the coroutine running in parallel. Displaying the context helped in narrowing down.

[2020-11-20T08:47:47.858 Thread=main @coroutine#2] [[CoroutineId(2), "coroutine#2":StandaloneCoroutine{Active}@3d04a311, BlockingEventLoop@7a46a697]] Launching coroutineA
[2020-11-20T08:47:47.912 Thread=main @coroutine#2] [[CoroutineId(2), "coroutine#2":ScopeCoroutine{Active}@57fa26b7, BlockingEventLoop@7a46a697]] Starting coroutineA()
[2020-11-20T08:47:47.921 Thread=main @coroutine#3] Launching coroutineB
[2020-11-20T08:47:47.922 Thread=main @coroutine#3] [[CoroutineId(3), "coroutine#3":ScopeCoroutine{Active}@44e81672, BlockingEventLoop@7a46a697]] Starting coroutineB()
[2020-11-20T08:47:48.929 Thread=DefaultDispatcher-worker-6 @coroutine#17] [[CoroutineId(17), "coroutine#17":StandaloneCoroutine{Active}@7e782624, Dispatchers.Default]] B4
[2020-11-20T08:47:48.929 Thread=DefaultDispatcher-worker-5 @coroutine#4] [[CoroutineId(4), "coroutine#4":StandaloneCoroutine{Active}@28a58b8f, Dispatchers.Default]] A1

Adding the dispatcher type changes from blockingEvenLoop to standalone coroutine.

Upvotes: 3

Related Questions