Reputation: 4991
I'm using Kotlin in my API backend. I don't want to run db queries in the common pool
. Basically, I want to create a CoroutineContext
that has a number of threads that matches the database maximumPoolSize
.
What's the best way to accomplish this (generally and for my specific use case)? I know Kotlin provides contexts
out of the box, but what's the best approach to create my own?
Bonus question: If I have a jdbc connection pool size of 3, does it make sense to use a coroutinecontext with a thread pool size of 3? Can this guarantee the best concurrency possible?
Upvotes: 3
Views: 3883
Reputation: 1186
The answer by zsmb13 works perfectly, but Android Studio warns that newFixedThreadPoolContext
is a delicate API and should only be used in specific cases.
The recommended alternative (as of Spring 2022) for limited parallelism is limitedParallelism
:
Creates a view of the current dispatcher that limits the parallelism to the given value. The resulting view uses the original dispatcher for execution, but with the guarantee that no more than parallelism coroutines are executed at the same time.
This method does not impose restrictions on the number of views or the total sum of parallelism values, each view controls its own parallelism independently with the guarantee that the effective parallelism of all views cannot exceed the actual parallelism of the original dispatcher.
So an alternative solution would be to create a view on the thread pool used for the db connection like:
val dbDispatcher = Dispatchers.IO.limitedParallelism(maximumPoolSize)
and then use this as coroutine dispatcher.
Upvotes: 1
Reputation: 923
The function newFixedThreadPoolContext
is now considered obsolete with current version of Kotlin coroutines (1.3.0), as it is now annotated with @ObsoleteCoroutinesApi
and it will give you a warning if you would try to use. The documentation also states that it will be replaced in the future.
The recommended way to create a CoroutineContext is now through
Executors.newFixedThreadPool(3).asCoroutineDispatcher()
So a complete example with imports, where also creating a CoroutineScope, would look like this
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executors
import kotlin.coroutines.CoroutineContext
fun coroutineScope(threads: Int): CoroutineScope {
val context: CoroutineContext = Executors.newFixedThreadPool(threads).asCoroutineDispatcher()
return CoroutineScope(context)
}
Upvotes: 6
Reputation: 89568
You can create a CoroutineContext
that's backed by a thread pool with a fixed number of threads using newFixedThreadPoolContext
:
val myContext = newFixedThreadPoolContext(nThreads = 3, name = "My JDBC context")
And yes, it seems like a good idea to match your thread pool's size to the connection pool's size, because that way your threads (assuming they each use one connection at a time) will always have a database connection ready for them - here's a blog post suggesting the same.
Upvotes: 5