Difference between ExecutorCoroutineDispatcher and CoroutineDispatcher
Asked Answered
H

1

5

Can someone please explain the difference between Kotlin Coroutine's ExecutorCoroutineDispatcher and CoroutineDispatcher from practical point of view, i.e. in which scenarios to use one against another?

So far I've been using Dispatchers, but (as far as I see) it can't give me a single background thread. That's the reason I'm using newSingleThreadExecutor().

What I've noticed though is that my main process never ends while using ExecutorCoroutineDispatcher (1) (with CoroutineDispatcher it finished as expected (2)). After some investigation it appears that I should run method close() on ExecutorCoroutineDispatcher for the main process to be finished (3). With CoroutineDispatcher you don't have to do this, it doesn't even have method close() (4). Is CoroutineDispatcher closed automatically? Why do we have closure process for ExecutorCoroutineDispatcher, but not for CoroutineDispatcher?

Below is a code I've used for testing:

fun main() = runBlocking<Unit> {
    val dispatcher1 = Executors.newSingleThreadExecutor().asCoroutineDispatcher() // (1) <-- main process runs indefinitely w/o closing dispatcher1 (3)
    val dispatcher2 = Dispatchers.Unconfined // (2)
    println("Start")

    launch(dispatcher1) {
        println("Child")
        delay(1000)
        printInfo(coroutineContext, this)
    }.join()

    println("End")
    dispatcher1.close() // (3) <-- need to close dispatcher1 for the main process to finish, otherwise it runs indefinitely
//    dispatcher2.close() // (4) <-- dispatcher2 doesn't have method 'close()'
}
Hexagram answered 14/11, 2019 at 10:36 Comment(0)
X
6

Is CoroutineDispatcher closed automatically? Why do we have closure process for ExecutorCoroutineDispatcher, but not for CoroutineDispatcher?

The difference is not in the dispatcher type, but in how the underlying Java Executor Service is configured. The default shared executors use daemon threads, which don't prevent the JVM from shutting down. If you want to, you can get the same for your own executors:

val myExecutor = Executors.newSingleThreadExecutor { task ->
    Thread(task).also { it.isDaemon = true }
}

val myDispatcher = myExecutor.asCoroutineDispatcher()

suspend fun main() {
    withContext(myDispatcher) {
        println("On my dispatcher")
    }
}
Xiphoid answered 14/11, 2019 at 11:9 Comment(4)
So for this case the difference in both is in different types of Java Executor Service?Hexagram
Not sure what you're asking. In my code there's just one executor service.Xiphoid
I mean, coroutine's Dispatchers methods provide dispatchers, which are using daemon threads inside, while ExecutorCoroutineDispatcher (in my case) is using a newly created non-daemon thread, is that correct?Hexagram
Yes, you used newSingleThreadedExecutor which uses the default settings and creates a non-daemon thread.Xiphoid

© 2022 - 2024 — McMap. All rights reserved.