Are you dealing with the RejectedExecutionException?

One of the things I encounter from time to time is the missing handling of the RejectedExecutionException (thrown by the Executor). This exception can be thrown when the executor:

  1. is shutting down. When it is shutting down, you don’t want it to execute accept new task: the shutdown should have a higher priority than the acceptance of new tasks.
  2. the executor doesn’t want to accept the task. If you are using a bounded BlockingQueue as workqeue in the ThreadPoolExecutor (bounded = good, makes your system degrade gracefully) and the queue is full, the Executor doesn’t block until the task can be placed (this is something not all developers realize), but rejects the tasks by throwing the RejectedExecutionException.

So the RejectedExecutionException is a ‘normal’ situation that could happen in a healthy system. So make sure you are dealing with the RejectedExecutionException. If you don’t deal with this situation, unwanted behavior, like disappearance of tasks, could be the consequence.

10 Responses to Are you dealing with the RejectedExecutionException?

  1. Pangea says:

    Hi – nice post….just what I was looking for…what do u think is the best way to handle this exception…

    In my app we TRY to execute tasks in async IF POSSIBLE. So I am thingking of handling this exception as below…let me know if there is a better way

    List tasksToPillSequentially=new ArrayList();

    try
    {
    executorService.submit(task);
    }
    catch(RejectedExecutionException re)
    {
    tasksToPillSequentially.add(task);
    }

    for(Task task: tasksToPillSequentially)
    {
    task.execute()
    }

    Thanks in advance!

  2. pveentjer says:

    Depending on the situation, it could be a very good solution. Essentially it is the same behaviour the CallerRunsPolicy provides.

    But with asynchronous communication, you always have to ask yourself: does my system want to process too much work? If the executor starts complaining with a RejectedExecutionException, is my system overloaded?

    Ps:
    I think it is really crap that the ThreadPoolExecutor doesn’t block out of the box. That is why I created the BlockingExecutor quite some time ago:
    http://prometheus.codehaus.org/javadoc/main/org/codehaus/prometheus/blockingexecutor/BlockingExecutor.html. If you want I can give you some pointers how to make the normal ThreadPoolExecutor blocking..

    Prometheus at the moment is not active, I’m spending all my time on http://multiverse.googlecode.com.. Prometheus = old school and old school concurrent is way too complex.

  3. Pangea says:

    thx for the response…i will stick with my current design…the reason for not using CallerRunsPolicy is that it will DISCARD the tasks if the thread pool/executor is shutdown…thats a bummer…the tasks should always be executed in my case; async if possible, sequentially otherwise.

    I’ve seen the MultiVerse project earlier…do u need any help on that…I’d like to contribute

  4. pveentjer says:

    Multiverse needs all the help it can get 🙂 So if you want to help, you are welcome!

  5. Pangea says:

    great..starting with Recommended literature….

  6. KIRU says:

    nice blog.. i am also facing the same exception in my android application downloading images in background and updating UI all the time . I feel in my situation it is full of pool.If i handled the exception what are consequences i will face? Since it is once issue to me i am unable to check could you suggest.

  7. shashikant says:

    Getting below exeption

    Configured in bean.xml like this

    Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘TaskExecutor’ defined in file [C:\EclipseWorkSpaces\Unity_SVN_WS\SpringMultiThreading\src\applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.codehaus.prometheus.blockingexecutor.ThreadPoolBlockingExecutor]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.codehaus.prometheus.blockingexecutor.ThreadPoolBlockingExecutor.()

  8. Gili Nachum says:

    I simply manually check for the queue current size, sleeping for 10ms until it has room for the new task:

    void executeOnPool(Runnable runnable) {
    while (workQueue.size()>=MAX_QUEUE_SIZE) {
    Thread.sleep(10);
    }
    pool.execute(runnable);
    }

    Agree that the default behavior should be to block instead of throwing an exception.

    • pveentjer says:

      Hi Gill,

      thanks for your post.

      Afaik your code has a datarace, it can be that thread1 sees that the workQueue.size() < MAX_QUEUE_SIZE, so concludes that it can continue to the pool.execute(runnable) but hasn't executed the call. If another thread would do the same thing at the same moment, thread1 could run into a RejectedExecutionException since assumption that there was space on the queueQueue, is broken.

      The problem can be solved by accessing the workQueue directly and putting the task on the queue instead of messing with the executor. It also prevents running into a 'busy' wait (although with the Thread.sleep(10) it isn't really spinning).

      • gilinachum says:

        Hi Peter.
        Thanks for noticing. I believe you are technically correct!
        It’s just that in my specific use case, I have a *single* dispatcher and N workers threads, so I didn’t have to worry about a potential data race. I guess it could easily be solved by synching the method (a small critical section overall).

        I agree that a full solution is your BlockingExecutor, I was merely noting the path I ended up taking for those who can’t introduce 3rd party code, and need a quick, yet limited, solution.
        Gili.

Leave a comment