Garrick
Garrick

Reputation: 689

Why the coroutine scope launches are run by different thread?

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

private val started = System.currentTimeMillis()

suspend fun main(args: Array<String>) {
    debug("Start run blocking")
    debug("starting")
    coroutineScope {
        debug("Inside runBlocking")
        val time = measureTimeMillis {
            val one = launch { doSomethingUsefulOne() }
            val two = launch { doSomethingUsefulTwo() }
            debug("awaiting")
//            two.await()
//            one.await()
            debug("Finished")
        }
        debug("time = $time")
    }
    debug("ending")
    debug("End run blocking")
}

suspend fun doSomethingUsefulOne(): Int {
    debug("Inside doSomethingUsefulOne")
    delay(3000L)
    debug("first")
    return 13
}

suspend fun doSomethingUsefulTwo(): Int {
    debug("Inside doSomethingUsefulTwo")
    delay(1000L)
    debug("second")
    return 29
}
private fun debug(s: String) {
    val elapsed = System.currentTimeMillis() - started
    println("[time elapsed : $elapsed] $s  --  ${Thread.currentThread()}")
}

I am working with above code to learn the behaviour of coroutines. I get the expected behaviour as follows:

[time elapsed : 15] Start run blocking  --  Thread[main,5,main]
[time elapsed : 16] starting  --  Thread[main,5,main]
[time elapsed : 34] Inside runBlocking  --  Thread[main,5,main]
[time elapsed : 77] Inside doSomethingUsefulOne  --  Thread[DefaultDispatcher-worker-1,5,main]
[time elapsed : 80] awaiting  --  Thread[main,5,main]
[time elapsed : 80] Finished  --  Thread[main,5,main]
[time elapsed : 80] Inside doSomethingUsefulTwo  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 80] time = 46  --  Thread[main,5,main]
[time elapsed : 1089] second  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 3088] first  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 3089] ending  --  Thread[DefaultDispatcher-worker-2,5,main]
[time elapsed : 3089] End run blocking  --  Thread[DefaultDispatcher-worker-2,5,main]

Here, I am unable to follow how launches were run on different thread as it should leverage Main thread(If I am right here). Also, outside the coroutineScope its the worked thread which print the last 2 statements as this should be run by main thread.

I want to know where am i going wrong ?

Upvotes: 2

Views: 1346

Answers (1)

Joffrey
Joffrey

Reputation: 37700

You never specify any coroutine dispatcher to launch your coroutines here. The suspend fun main gives you an empty context (without dispatcher), and coroutineScope also doesn't add any dispatcher.

You then use launch without argument to start your 2 coroutines. As the doc says:

If the context does not have any dispatcher nor any other ContinuationInterceptor, then Dispatchers.Default is used.

This means that your coroutines will be dispatched using Dispatchers.Default which provides multiple worker threads based on the number of CPU cores you have.

If you wanted to run these coroutines on the main thread, you could use launch(Dispatchers.Main) instead (but it's only available in special environments like Android and JavaFX AFAIK).

Upvotes: 3

Related Questions