ThreadPoolExecutor - dynamic configuration, pool size vs queue size

942 views Asked by At

In a java project, in order to execute tasks in an asynchronous manner I'm using ThreadPoolExecutor. As expected while I'm creating my executor I'm setting the core and max pool sizes and a bounded (fixed-capacity) queue as well.

If my tasks get rejected (all threads are busy and the queue is full) I'm increasing dynamically the max-pool-size of my executor, this way I get more threads pulling tasks from my queue.

This is the standard approach I have been using so far but lately I encountered a different approach:

In this approach you set core and max pool sizes and an unbounded queue and you limit your queue as follows:

public class AsyncTaskexecutor {

    private ThreadPoolExecutor threadPoolExecutor;
    private int maxTasksInQueue;
    private BlockingQueue queue;
    
    public AsyncTaskexecutor(ThreadPoolExecutor threadPoolExecutor) {
        this.queue = new LinkedBlockingQueue<>(); // creaing unbounded queue
        this.threadPoolExecutor = createThreadPoolExecutor();
        this.maxTasksInQueue = 100;
    }
    
    /**
    * @return true if the task is either executed or pending in the queue for execution, else false (meaning rejected) 
    **/
    public boolean executeAsync(Runnable task) {
        if(this.queue.size() < maxTasksInQueue) {
            threadPoolExecutor.execute(task);
            return true;
        } else {
            return false; // rejected
        }
    }
    
    private ThreadPoolExecutor createThreadPoolExecutor() {
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, this.queue, threadFactory, ThreadPoolExecutor.AbortPolicy);
        return executor;
    }
    
    public void setQueueSize(int newSize) {
        this.maxTasksInQueue = newSize;
    }
}

So once tasks are rejected it is possible to call the setQueueSize method and dynamically increase the number of elements in the queue. In the first approach we can play with max-pool-size which means we are bound to cpu resource while in the second approach we can play with the number of tasks in the queue which means we are bound to memory resource.

Are both approaches valid to handle bursts of tasks (avoid rejection as much as possible)? Any other advantages/disadvantages I am missing here?

0

There are 0 answers