0
votes

Just started learning Kotlin and I am trying to make sense of the output of the code snippet below. Per my understanding, the output should be in this order -

Right After Thread.sleep call - from main thread
mainline - from main thread
launched in new thread - from pool-1-thread-1 thread

  1. The first coroutine is created and passed to new thread for execution and suspend for 2 secs.
  2. Second coroutine is launched in main thread. Block the main thread for 0.5 sec and print.
  3. Main thread get unblocked, and third print statement is executed.
  4. Lastly, the first coroutine resume execution after 2 secs delay and prints the statement.

However, the actual result printed is -

launched in new thread - from pool-1-thread-1 thread
mainline - from main thread
Right After Thread.sleep call - from main thread

Greatly appreciate if someone could help me understand the logic behind it

fun main() = runBlocking {


    val es = Executors.newSingleThreadExecutor()

    withContext (es.asCoroutineDispatcher()) {

        delay(2000L)
        println("launched in new thread - from ${Thread.currentThread().name} thread")
    }

    launch {

        Thread.sleep(500L)
        println("Right After Thread.sleep call -  from ${Thread.currentThread().name} thread")
    }

        println("mainline - from ${Thread.currentThread().name} thread")
        es.shutdown()
}

1
Why do you expect the second coroutine to be run in the main thread?Louis Wasserman
@LouisWasserman, because there is only main thread other than the one explicitly created to run first coroutine.FoxRiver
@IR42 pardon my ignorance. Even in that case too, third print statement should follow the second print and not vice versa since the second coroutine has blocked the main thread with Thread.sleep call.FoxRiver

1 Answers

0
votes

You should read the documentation

Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns the result. ... withContext

Launches a new coroutine without blocking the current thread ... By default, the coroutine is immediately scheduled for execution. Other start options can be specified via start parameter. ... launch

Default – immediately schedules the coroutine for execution according to its context. ... the coroutine code is dispatched for execution later, while the code that invoked the coroutine builder continues execution. ...CoroutineStart.DEFAULT

It means that

  • first withContext is executed
  • next a new coroutine is created and scheduled
  • then println("mainline - from ${Thread.currentThread().name} thread") es.shutdown() is executed
  • and finally the coroutine block is executed