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?
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