I am complete new to Kotlin so please bear with me. My problem: I am developing an API that will query a database. The database provides JDBC connector that is blocking and my queries will be long-running (up to 60s). Is it possible to turn the blocking code into non-blocking with Kotlin? How? Example code would be appreciated. Thanks.
Well, yes and no. We can’t anyhow turn blocking operation into non-blocking. But we can handle it in a smart way, so most of our code is non-blocking.
While using Kotlin coroutines, we can do it simply by:
with (Dispatchers.IO) {
// blocking operation
}
Internally, it schedules the operation using a special thread pool, but the calling thread is only suspended and can do something else.
If not using coroutines then I believe Kotlin doesn’t provide any tools for this.
Do you mean withContext(...)?
Yes, I meant withContext() ![]()
It is not possible to turn blocking code into a non-blocking. Unless project Loom fulfills its promise and even in this case it probably won’t be fully automatic. In Kotlin you can call blocking code asynchronously. Though it will still block a thread it is called on.
Yeah basically what broot and thumannw said; use withContext().
Let’s say your blocking database call looks like this:
database.withHandle { it.createQuery("get-my-data.sql").list() }
Put that code inside a withContext lambda, like so:
withContext(Dispatchers.IO) {
database.withHandle { it.createQuery("get-my-data.sql").list() }
}
This will run the code inside the withContext lambda on the Dispatchers.IO coroutine dispatcher; essentially what happens is your blocking code is run on a different thread, while your calling thread is suspended while waiting for the blocking code to complete. It doesn’t stop the blocking code from blocking a thread, but since it blocks a thread in a threadpool and suspends your calling thread, you still get the effect you want. ![]()
If you want to make it more dynamic, and allow consumers of your API to provide their own threadpool/dispatcher for running blocking code, you could do something like the following:
suspend fun <T> makeBlockingCodeSuspend(
dispatcher: CoroutineDispatcher? = null,
block: suspend CoroutineScope.() -> T
) = withContext(dispatcher ?: Dispatchers.IO, block)
EDIT: Anyone know how to make Dispatchers.IO not show up as a hyperlink?
Like this: Dispatchers.IO