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

Andrea Giuliano

07/23/2020, 7:43 PM
Hi guys, I’m playing with Kotlin coroutines and there is something I don’t understand. Here’s my code
Copy code
val myScope = CoroutineScope(Executors.newFixedThreadPool(1).asCoroutineDispatcher())

@Test
fun testCoroutines() = runBlocking<Unit>(myScope.coroutineContext) {
    myScope.launch() {
        println("first 1")
        delay(100)
        println("first 2")
    }
    myScope.launch() { println("second") }
}
Can someone explain to me why I will never see “first 2" printed? if I dont use myscope.launch all works as expected and I see the 3 lines printed. That makes sense since the launch coroutines inherit the scope from runBlocking. But if I set it explicitly something changes not sure why (edited)
o

octylFractal

07/23/2020, 7:44 PM
If I had to guess, the test finishes before the delay is up, and the JVM shuts down nothing is restricting those launches to the runtime of
testCoroutines
when you do a normal
launch
instead of prefixing it, they become children of `runBlocking`'s scope, and
runBlocking
will wait for them to finish before returning
☝️ 2
z

Zach Klippenstein (he/him) [MOD]

07/23/2020, 7:49 PM
The
CoroutineScope
function will create a
Job
for itself if the context you pass doesn’t contain one. Since you’re only passing a dispatcher, it doesn’t, so the scope will get its own job. I think this would work as expected if you only passed the dispatcher itself directly to
runBlocking
, in that case
runBlocking
would use its own
Job
as the parent, and would be aware that there are two coroutines which need to both finish.
E.g.
Copy code
val myContext = Executors.newFixedThreadPool(1).asCoroutineDispatcher()

@Test
fun testCoroutines() = runBlocking<Unit>(myContext) {
  …
j

julian

07/23/2020, 8:42 PM
In order for
launch
to prevent
runBlocking
from exiting, there has to be parent-child relationships between `runBlocking`'s
Job
, and the
Job
of each
launch
. As the code is currently written, that relationship is never established.
a

Andrea Giuliano

07/23/2020, 8:47 PM
gotcha so if I'm understanding this right it is true that test and the 2 coroutines will run in the same threadpool but since there is no hierarchy parent children then although I'm explicitly setting runblocking they will all go in parallel no matter what.
a bit weird since I was expecting run blocking to wait for all the coroutines launched inside it
z

Zach Klippenstein (he/him) [MOD]

07/23/2020, 8:51 PM
Yep. The only way coroutines know about what was “launched inside it” is through the Job hierarchy.
a

Andrea Giuliano

07/23/2020, 8:53 PM
gotcha thanks for your help guys
j

julian

07/23/2020, 8:57 PM
...although I'm explicitly setting runblocking they will all go in parallel no matter what
Technically, I think even when the job hierarchy is properly established, it's still correct to say that the coroutines run concurrently, even if
runBlocking
waits for the
launch
s to complete.
o

octylFractal

07/23/2020, 9:00 PM
note that "parallel" and "concurrently" are slightly different terms -- coroutines are always concurrent, they always are capable of processing multiple tasks, even with a single thread, and if you properly
suspend
they can interleave with eachother. coroutines are not always parallel, such as in the current setup displayed here. They do not always run multiple tasks at the same time, only if there are multiple threads is that possible
☝️ 3
j

julian

07/23/2020, 9:06 PM
Yup, in this case the thread pool is limited to
1
, so it can be concurrent, but not parallel.
a

Andrea Giuliano

07/23/2020, 9:08 PM
correct, I wanted to just make sure the coroutines run on that isolated threadpool
3 Views