Hey Kotliners, I am puzzled by one behaviour in `...
# coroutines
d
Hey Kotliners, I am puzzled by one behaviour in
async
function. Here is the use case:
Copy code
val deferred1 = GlobalScope.async {
   // rest-call-one
}

val deferred2 = GlobalScope.async {
   // rest-call-one
}

val deferred3 = GlobalScope.async {
   // rest-call-one
}

runBlocking {
    deferred1.await()
    deferred2.await()
    deferred3.await()
}
I have added some metrics to capture how well these are executed. Each of the calls take 20ms however, collectively they take 200ms. The CPU metrics shows that these threads are not getting starved. The usage is pretty low. I am wondering is this the right way to use
async
any guidance would be really helpful. Thank you.
r
Ideally you would do the following:
Copy code
coroutineScope {
    launch {
        // rest-call-one
    }

    launch {
        // rest-call-two
    }

    launch {
        // rest-call-three
    }
}
Outer scope would wait for everything to finish. Replace launches with async-await if you need results (you didn't use it so launch is more logical).
d
Hello Andrew, Thanks for your help. Yes, I can replace
async
I am not using that. the new code looks like
Copy code
runBlocking {
    corouteScope {
        // All launch here 
    }
}
Is this the right way to use it?
r
runBlocking
creates it's scope, so you don't need an additional one. Though
runBlocking
, well, blocks, so make sure that's the thing you really need. To my experience,
runBlocking
is often used as a single bridge between blocking and suspending worlds -- e.g. in your
main
, in route handler for backend frameworks not supporting coroutines natively, in test methods. You don't need it when you, for example, already entered suspending world.
l
Also,
runBlocking
has a single thread in its dispatcher, so if it's blocked by some work… you know that the other work will be blocked for that time.
r
Oh wow, that's news to me. Thanks, additional point for future replies like this :)
l
It's all in the doc. You can pass
Dispatchers.Default
or whatever to
runBlocking
if needed of course.
d
Well, I am more confused now. In java, I would use a fork join pool and wait till all 3 tasks are done. How do I do that in Kotlin? Even though I have a suspended method, I need to call it inside a context which grantees that the thread waits till all 3 tasks are done.
l
@Dibya Ranjan There's this great talk about structured concurrency that might help you understand things:

https://www.youtube.com/watch?v=Mj5P47F6nJg

The rest, reading the docs should be helpful.
🙏 1