Search code examples
multithreadingkotlinconcurrencyjava.util.concurrentthreadpoolexecutor

ThreadPoolExecutor - Can I throw exception if pool is full


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. ")
    }
}

Solution

  • 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:

    • 0 seconds (3rd and 4th arguments) correspond to the core thread keep-alive time. Setting 0 means your core threads will never be stopped even if they remain idle. This is the default behaviour when using Executors.newFixedThreadPool(4).
    • Executors.defaultThreadFactory() is the default thread factory, same as when using Executors.newFixedThreadPool(4).
    • Here core and max thread pool size is set to 4 (1st and 2nd argument), which for your use case seems appropriate.
    • 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.