kotlinkotlin-coroutines

Why doesn't a runBlocking block with a newSingleThreadExecutor end?


I'm trying to figure out why this code is running infinitely:

fun main() = runBlocking {
launch {
    delay(200L)
    println("Task from runBlocking $coroutineContext")
}

// This is the important part: if I uncomment this line and comment next line, then it will finish running
//    coroutineScope { 
CoroutineScope(Executors.newSingleThreadExecutor().asCoroutineDispatcher()).launch {
    launch {
        delay(500L)
        println("Task from nested launch $coroutineContext")
    }

    delay(100L)
    println("Task from coroutine scope $coroutineContext")
}

println("Coroutine scope is over")
}

When I run this code, I see this output:

Coroutine scope is over
Task from coroutine scope [StandaloneCoroutine{Active}@5287ba83, java.util.concurrent.Executors$FinalizableDelegatedExecutorService@91445f6]
Task from runBlocking [StandaloneCoroutine{Active}@28ac3dc3, BlockingEventLoop@32eebfca]
Task from nested launch [StandaloneCoroutine{Active}@702cf19c, java.util.concurrent.Executors$FinalizableDelegatedExecutorService@91445f6]

but the program never ends... As I wrote in the comment, if I replace newSingleThreadExecutor line with just a simple coroutineScope, then it completes quickly.

Why doesn't this code exit running?


Solution

  • The reason for this is because non-daemon threads keep the JVM alive.

    You need to shutdown your ExecutorService to properly let the JVM finish its execution.

    This has been answered here: ExecutorService JVM doesn't terminate