Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why runBlocking is not blocking the invoking thread

I'm trying to understand runBlocking in kotlin.

 println("before runBlocking ${Thread.currentThread().name}")

    runBlocking { // but this expression blocks the main thread
        delay(2000L) // non blocking
        println("inside runBlocking ${Thread.currentThread().name}")
        delay(2000L)
    }

    println("after runBlocking ${Thread.currentThread().name}")

Output

before runBlocking main
inside runBlocking main
after runBlocking main

Kotlin Says

  1. runBlocking - Runs a new coroutine and blocks the current thread interruptibly until its completion
  2. The main thread invoking runBlocking blocks until the coroutine inside runBlocking completes.

point 1 :- if runBlocking blocked the main thread in above example. Then inside runBlocking how i get the main thread again.

point 2 :- if Runs a new coroutine is true in above statement, then why it didn't create new coroutine inside runBlocking.

like image 220
Vikas Acharya Avatar asked Sep 15 '25 06:09

Vikas Acharya


1 Answers

The signature of runBlocking (doc) is

fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> T
): T (source)

If you see the context param, it has a default of an EmptyCoroutineContext. Hence when you don't pass a specific context, the default value is an event loop on the current thread. Since the current thread before running the runBlocking block was the main thread, whatever you ran inside the block is still on the main thread.

If you pass a coroutine context as below, you would have the block inside runBlocking running in a different thread.

println("before runBlocking ${Thread.currentThread().name}")

runBlocking(Dispatchers.Default) {
    delay(2000L)
    println("inside runBlocking ${Thread.currentThread().name}")
    delay(2000L)
}

println("after runBlocking ${Thread.currentThread().name}")

Output

before runBlocking main
inside runBlocking DefaultDispatcher-worker-1
after runBlocking main

Or if you launch runBlocking without passing the context, but launch a coroutine inside as below, you would see it running on the different thread.

println("before runBlocking ${Thread.currentThread().name}")

runBlocking { 
    println("inside runBlocking ${Thread.currentThread().name}")
    delay(2000L) 
    CoroutineScope(Dispatchers.Default).launch {
        println("inside runBlocking coroutineScope ${Thread.currentThread().name}")
    }
    delay(2000L)
}

println("after runBlocking ${Thread.currentThread().name}")

Output

before runBlocking main
inside runBlocking main
inside runBlocking coroutineScope DefaultDispatcher-worker-1
after runBlocking main
like image 190
Madhu Bhat Avatar answered Sep 18 '25 04:09

Madhu Bhat