Is it possible to throw exception if incoming request can't be handled?
So, I have some fixed thread pool:
private val executor: ThreadPoolExecutor = Executors.newFixedThreadPool(4) as ThreadPoolExecutor
And I don't want requests go to thread queue if can't be handled, I just want to throw exception.
I'm trying to check activeCount and throw exception if is greater than max pool size but it's not working just like I want.
private fun checkPoolSize() {
if (executor.activeCount >= 4) {
throw RuntimeException("Request can't be handled. ")
}
}
One solution for this is to use a queue of capacity 0 and java.util.concurrent.ThreadPoolExecutor.AbortPolicy as a RejectedExecutionHandler.
The static methods in Executors do not expose the full set of parameters you want for this, so you will need to instantiate a ThreadPoolExecutor directly. In your case, you could use the following:
new ThreadPoolExecutor(4, /* Core pool size */
4, /* Max pool size */
0, TimeUnit.SECONDS, /* Core th. keep-alive */
new MyQueue<Runnable>(0), /* No queueing allowed */
Executors.defaultThreadFactory(), /* default */
new AbortPolicy()) /* throws when all core threads busy */
A few notes:
Executors.newFixedThreadPool(4).Executors.defaultThreadFactory() is the default thread factory, same as when using Executors.newFixedThreadPool(4).MyQueue is an implementation of BlockingQueue which accepts 0 as a capacity (i.e. which can only be empty. This is of course not a queue but implementing this allows to seamlessly integrating with the ThreadPoolExecutor provided by the JDK.). Further consideration:
With such fine-tuning of your thread pool, beware that the throughput will be limited. Here, considering 4 threads and an average latency L in seconds for the tasks submitted to the thread pool, the average throughput allowed by this configuration is 4/L tasks/second.
You can use a saturation policy which comes in play when your bounded queue fills up. You can set a saturation policy by calling setRejectedExecutionHandler() of ThreadPoolExecutor. The out-of-the-box implementations are AbortPolicy, CallerRunsPolicy, DiscardPolicy and DiscardOldestPolicy. AbortPolicy is default which throws RejectedExecutionException when the bounded queue fills up. You can also provide your own custom implementation.