RejectedExecutionException

java.util.concurrent.RejectedExecutionException – How to solve RejectedExecutionException

In this example we are going to talk about java.util.concurrent.RejectedExecutionException. When using an Executor to run your threads, it might reach a state where it cannot run the task you asked him to. This can happen for a number of reason, as we will demonstrate in this example. It is worth noting that this is a java.lang.RuntimeException
 
 
 
 
 
 

1. A simple Executor Example

To demonstrate this exception we are going to create a simple Java application that uses a ThreadPoolExecutor to execute a number of worker threads. Let’s see how you can do that.

Here a simple worker thread:

Worker.java:

package com.javacodegeeks.core.rejectedexecutionexception;

public class Worker implements Runnable {
	
	private int ID;
	
	public Worker(int id){
        this.ID = id;
     }

	@Override
	public void run() {
		 try{
	            Thread curThread = Thread.currentThread();
	            System.out.println(curThread.getName() + " currently executing the task " + ID);
	            Thread.sleep(500);
	            System.out.println(curThread.getName() + " just completed the task " + ID);
	         }
	         catch(Exception e){
	            System.out.println(e);
	         }
		
	}

	public int getID() {
		return ID;
	}

	public void setID(int iD) {
		ID = iD;
	}
}

An here is how you can use an ThreadPoolExecutor to create a number of threads to execute your tasks

RejectedExecutionExceptionExample.java:

package com.javacodegeeks.core.rejectedexecutionexception;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RejectedExecutionExceptionExample {

	public static void main(String[] args) {
		
		ExecutorService executor = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(15));

        Worker tasks[] = new Worker[10];
        for(int i=0; i<10; i++){
           tasks[i] = new Worker(i);
           executor.execute(tasks[i]);
        }
           executor.shutdown();		
	}
}

If you run the program, this is the output:

pool-1-thread-2 currently executing the task 1
pool-1-thread-3 currently executing the task 2
pool-1-thread-1 currently executing the task 0
pool-1-thread-1 just completed the task 0
pool-1-thread-2 just completed the task 1
pool-1-thread-1 currently executing the task 3
pool-1-thread-3 just completed the task 2
pool-1-thread-2 currently executing the task 4
pool-1-thread-3 currently executing the task 5
pool-1-thread-3 just completed the task 5
pool-1-thread-1 just completed the task 3
pool-1-thread-2 just completed the task 4
pool-1-thread-1 currently executing the task 7
pool-1-thread-3 currently executing the task 6
pool-1-thread-2 currently executing the task 8
pool-1-thread-2 just completed the task 8
pool-1-thread-3 just completed the task 6
pool-1-thread-1 just completed the task 7
pool-1-thread-2 currently executing the task 9
pool-1-thread-2 just completed the task 9

Everything went normal at this point. We create a ThreadPoolExecutor with pool size of 3. This means that it will create 3 threads that will be charged with the execution of our tasks-workers. As we submit new tasks to the ThreadPoolExecutor, he will place them in a BlockingQueue, as some of its 3 threads might be currently occupied with other tasks and thus the new tasks will have to wait until one of these 3 threads becomes available. In this particular case we use an ArrayBlockingQueue of size 15, to do this job (for reason that should become clear later on). After that, we create 10 tasks and we submit them to out ThreadPoolExecutor.

2. A simple case of RejectedExecutionException

One of the causes of RejectedExecutionException is when we try to execute a new task after we’ve shutdown the executor. When shutdown() is called upon an executor, older tasks might still progress, but it allows no more tasks to be submitted.

Let’s see what happens in the case where we violate this rule :

RejectedExecutionExceptionExample.java:

package com.javacodegeeks.core.rejectedexecutionexception;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RejectedExecutionExceptionExample {

	public static void main(String[] args) {
		
		ExecutorService executor = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(15));

        Worker tasks[] = new Worker[10];
        for(int i=0; i<10; i++){
           tasks[i] = new Worker(i);
           executor.execute(tasks[i]);
        }
           executor.shutdown();		
           executor.execute(tasks[0]);
	}
}

If you run the program, this is the output:

pool-1-thread-2 currently executing the task 1
Exception in thread "main" pool-1-thread-3 currently executing the task 2
pool-1-thread-1 currently executing the task 0
java.util.concurrent.RejectedExecutionException: Task com.javacodegeeks.core.rejectedexecutionexception.Worker@1e344422 rejected from java.util.concurrent.ThreadPoolExecutor@796523ab[Shutting down, pool size = 3, active threads = 3, queued tasks = 7, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.reject(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)
	at com.javacodegeeks.core.rejectedexecutionexception.RejectedExecutionExceptionExample.main(RejectedExecutionExceptionExample.java:21)
pool-1-thread-2 just completed the task 1
pool-1-thread-1 just completed the task 0
pool-1-thread-2 currently executing the task 3
pool-1-thread-3 just completed the task 2
pool-1-thread-1 currently executing the task 4
pool-1-thread-3 currently executing the task 5
pool-1-thread-3 just completed the task 5
pool-1-thread-2 just completed the task 3
pool-1-thread-1 just completed the task 4
pool-1-thread-2 currently executing the task 7
pool-1-thread-3 currently executing the task 6
pool-1-thread-1 currently executing the task 8
pool-1-thread-3 just completed the task 6
pool-1-thread-2 just completed the task 7
pool-1-thread-1 just completed the task 8
pool-1-thread-3 currently executing the task 9
pool-1-thread-3 just completed the task 9

So when shutdown() is called, no more tasks are allowed to be executed. If that is not so, RejectedExecutionException is raised.

3. A second case of RejectedExecutionException

Another case of RejectedExecutionException, appears when an Executor cannot take any more tasks under its responsibility. This happens when the limit of its local “memory” is reached. In our case that “local” memory is an ArrayBlockingQueue of size 15. If we try to submit more tasks than the ArrayBlockingQueue can hold, then RejectedExecutionException arises.

Let’s see an example :

RejectedExecutionExceptionExample.java:

package com.javacodegeeks.core.rejectedexecutionexception;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RejectedExecutionExceptionExample {

	public static void main(String[] args) {
		
		ExecutorService executor = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(15));

        Worker tasks[] = new Worker[20];
        for(int i=0; i<20; i++){
           tasks[i] = new Worker(i);
           executor.execute(tasks[i]);
        }
           executor.shutdown();		
           executor.execute(tasks[0]);
	}
}

Now as you can, see our ArrayBlockingQueue can hold no more than 15 threads. But we submit to it 20 threads. And because we’ve introduced a bit of delay in the threads (with Thread.sleep()), our 3 workers are occupied for sometime. So, our ThreadPoolExecutor has to put newly submitted tasks to the ArrayBlockingQueue, because they cannot be executed instantly. Consequently, when the submitted tasks are more than he can handle (more than 15), then RejectedExecutionException is thrown.

4. How to solve RejectedExecutionException

The first things you want to check are the two cases :

  1. Be careful not to submit new tasks after having called shutdown() on the Executor.
  2. Do not give the Executor more tasks than he can handle.

Not surprisingly, the second case can be easily resolved. You could just use a data structure that does not impose a size limit. For example a LinkedBlockingQueue. So if you still face this problem after using LinkedBlockingQueue, you should focus on the first case. If the first case is not the cause of your problem, then you should probably look for more complex problem. For example, your memory is filling up because some of your threads have deadlocked and the LinkedBlockingQueue keeps filling up, and don’t forget is still the limit of the available memory that the JVM has.

I want to focus a bit more o that second case, as it might be hidden often. Do not forget that it is possible to submit more that 15 tasks in the ThreadPoolExecutor even in the case where he uses the ArrayBlockingQueue, as long as you give it some time to complete some of the tasks before submitting new ones, so that the 3 workers smoothly consume the ArrayBlockingQueue and does not get clogged up.

Let’s see this example :

RejectedExecutionExceptionExample.java:

package com.javacodegeeks.core.rejectedexecutionexception;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RejectedExecutionExceptionExample {

	public static void main(String[] args) throws InterruptedException {
		
		ExecutorService executor = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(15));

        Worker tasks[] = new Worker[20];
        for(int i=0; i<10; i++){
           tasks[i] = new Worker(i);
           executor.execute(tasks[i]);
        }
        Thread.sleep(3000);
        for(int i=10; i<20; i++){
            tasks[i] = new Worker(i);
            executor.execute(tasks[i]);
         }
           executor.shutdown();		
	}
}

From the output, you can see that the program is executed normally.

pool-1-thread-1 currently executing the task 0
pool-1-thread-3 currently executing the task 2
pool-1-thread-2 currently executing the task 1
pool-1-thread-1 just completed the task 0
pool-1-thread-3 just completed the task 2
pool-1-thread-1 currently executing the task 3
pool-1-thread-2 just completed the task 1
pool-1-thread-2 currently executing the task 5
pool-1-thread-3 currently executing the task 4
pool-1-thread-2 just completed the task 5
pool-1-thread-1 just completed the task 3
pool-1-thread-3 just completed the task 4
pool-1-thread-1 currently executing the task 7
pool-1-thread-2 currently executing the task 6
pool-1-thread-3 currently executing the task 8
pool-1-thread-1 just completed the task 7
pool-1-thread-3 just completed the task 8
pool-1-thread-2 just completed the task 6
pool-1-thread-1 currently executing the task 9
pool-1-thread-1 just completed the task 9
pool-1-thread-3 currently executing the task 10
pool-1-thread-1 currently executing the task 12
pool-1-thread-2 currently executing the task 11
pool-1-thread-3 just completed the task 10
pool-1-thread-1 just completed the task 12
pool-1-thread-1 currently executing the task 14
pool-1-thread-2 just completed the task 11
pool-1-thread-3 currently executing the task 13
pool-1-thread-2 currently executing the task 15
pool-1-thread-3 just completed the task 13
pool-1-thread-2 just completed the task 15
pool-1-thread-2 currently executing the task 17
pool-1-thread-1 just completed the task 14
pool-1-thread-3 currently executing the task 16
pool-1-thread-1 currently executing the task 18
pool-1-thread-1 just completed the task 18
pool-1-thread-3 just completed the task 16
pool-1-thread-2 just completed the task 17
pool-1-thread-1 currently executing the task 19
pool-1-thread-1 just completed the task 19

You should be careful, because you might thing that your ThreadPoolExecutor can successfully take more than 15 tasks, but that is only because the are being progressively consumed by the 2 workers.

Download the Source Code

This was an example of java.util.concurrent.RejectedExecutionException and How to solve RejectedExecutionException.

Download
You can download the full source code of this example here : RejectedExecutionExceptionExample.zip

Nikos Maravitsas

Nikos has graduated from the Department of Informatics and Telecommunications of The National and Kapodistrian University of Athens. During his studies he discovered his interests about software development and he has successfully completed numerous assignments in a variety of fields. Currently, his main interests are system’s security, parallel systems, artificial intelligence, operating systems, system programming, telecommunications, web applications, human – machine interaction and mobile development.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
betterThansYou
betterThansYou
6 years ago

Well that was 5 minutes of my life i can’t get back. How can you possibly think this is a reasonable solution to overloading tasks onto an executor ? Just put a sleep between batches of calls ???

sri
sri
5 years ago

output of the program
Given:
1. public class Threads2 implements Runnable {
2.
3. public void run() {
4. System.out.println(“run.”);
5. throw new RuntimeException(“Problem”);
6. }
7. public static void main(String[] args) {
8. Thread t = new Thread(new Threads2());
9. t.start();
10. System.out.println(“End of method.”);
11. }
12. }

Back to top button