Jim
Jim

Reputation: 19582

ThreadPoolExecutor and RejectedExecutionExceptionHandler

I want to use a bounded queue for a ThreadPoolExecutor but I want to use my custom RejectedExecutionExceptionHandler. I would need to do that so that I can put rejected tasks to a separate queue and after a while try to resubmit them.
Is a custom RejectedExecutionExceptionHandler the solution to my problem? If yes how do I implement one?
Or else what would be the best way to deal with my issue?

Upvotes: 2

Views: 792

Answers (2)

Geek
Geek

Reputation: 27203

In your case you would want to choose a saturation policy which comes to play only when the bounded queue gets filled up . The saturation policy for a thread pool executor can be modified by calling setRejectedExecutionHandler() method . There are four types of saturation policy :

  1. Abort ( this actually throws an exception and lets the caller deal with it )
  2. Discard( this actually discards the newly submitted task)
  3. Discard - oldest ( this discards the task that was to run next and tries to resubmit the new task)
  4. Caller-runs policy which implements some form of throttling that neither discards tasks nor throws an exception , but instead tries to slow down the flow of new tasks by pushing some of the work back to the caller . So the caller thread becomes busy running new tasks and thus can not accept any more tasks during that time .

For your situation I think CallerRunsPolicy() makes most sense . Do this :

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

Upvotes: 2

Peter Lawrey
Peter Lawrey

Reputation: 533670

I would use an unbounded queue as this will queue tasks which cannot be run for later use. I would sue Executors.newFixedThreadPool in your case. You may be interested in what this does

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

Note: it uses an unbounded queue.

IMHO the simplest/best way to deal with the problem is to run the task in the current thread.

This ensures all tasks are performed in a timely manner using the current thread where there is no spare background threads.

new RejectedExecutionHandler() {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        r.run();
    }
}

Upvotes: 1

Related Questions