java.util.concurrent.RejectedExecutionHandler Example
Here we will discuss about the RejectedExecutionHandler
Interface in the java.util.concurrent
package. This interface is really helpfull when working with the ThreadPoolExecutor
.
1. Overview & Usage
The interface java.util.concurrent.RejectedExecutionHandler
is a handler for tasks that cannot be executed by a ThreadPoolExecutor
( a class that implements ExecutorService
, ). This may occur when no more threads or queue slots are available because their bounds(limit of its local “memory”) would be exceeded, or upon shutdown of the Executor. The known implementation of the Interface are: ThreadPoolExecutor.AbortPolicy
, ThreadPoolExecutor.CallerRunsPolicy
, ThreadPoolExecutor.DiscardOldestPolicy
, ThreadPoolExecutor.DiscardPolicy
. First let us have a look to the Interface declaration:
public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }
1.1 The rejectedExecution(Runnable r,ThreadPoolExecutor e) method:
New tasks submitted in method execute(java.lang.Runnable)
will be rejected when the Executor
has been shut down, and also when no more threads or queue slots are available because their bounds(limit of its local “memory”) would be exceeded. In either case, the execute method invokes the RejectedExecutionHandler
.rejectedExecution(Runnable r,ThreadPoolExecutor e)
method of its RejectedExecutionHandler
. If no other alternative is available then it’s implementation may throw an unchecked RejectedExecutionException
, which will be propagated to the caller of execute()
.
2. Example
In order to show the use of the RejectedExecutionHandler
we have to use 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.example.rivu.rejectedexecutionhandlerexample; public class Worker implements Runnable { int id; String name="Worker"; public Worker(int id) { this.id=id; System.out.println("Worker "+id+" Created"); } @Override public void run() { // TODO Auto-generated method stub Thread curThread = Thread.currentThread(); try{ name=curThread.getName(); System.out.println(name + " Executing " + id); Thread.sleep(1000); System.out.println(name + " Completed " + id); } catch(Exception e){ System.out.println(e.getMessage()); } } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { // TODO Auto-generated method stub String s=name+" ID: "+id; return s; } }
The class in which we implemented the RejectedExecutionHandler
.
MyRejectedExecutionHandler.java:
package com.javacodegeeks.example.rivu.rejectedexecutionhandlerexample; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; public class MyRejectedExecutionHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable worker, ThreadPoolExecutor executor) { // TODO Auto-generated method stub System.out.println(worker.toString()+" is Rejected"); System.out.println("Retrying to Execute"); try{ //Re-executing with alternateExecutor RejectedExecutionHandlerExample.alternateExecutor.execute(worker); System.out.println(worker.toString()+" Execution Started"); } catch(Exception e) { System.out.println("Failure to Re-exicute "+e.getMessage()); } } }
RejectedExecutionHandlerExample.java:
package com.javacodegeeks.example.rivu.rejectedexecutionhandlerexample; import java.util.concurrent.*; import java.util.concurrent.ThreadPoolExecutor; public class RejectedExecutionHandlerExample { public static ThreadPoolExecutor executor=(ThreadPoolExecutor) Executors.newFixedThreadPool(5); public static ThreadPoolExecutor alternateExecutor=(ThreadPoolExecutor) Executors.newFixedThreadPool(5); public static void main(String[] args) { // TODO Auto-generated method stub RejectedExecutionHandler handler=new MyRejectedExecutionHandler(); executor.setRejectedExecutionHandler(handler); System.out.println("Starting ThreadPoolExecutor"); Worker[] workers=new Worker[10]; for(int i=0;i<10;i++){ workers[i]=new Worker(i); executor.execute(workers[i]); if(i==6) executor.shutdown();// The executor is terminated intentionally to check the RejectedExecutionHandler } executor.shutdown(); while(!executor.isTerminated()){ //Waiting for the termination of executor } System.out.println("Execution Completed"); alternateExecutor.shutdown(); while(!alternateExecutor.isTerminated()){ //Waiting for the termination of alternateExecutor } System.out.println("Alternate Execution Completed"); } }
Output
Starting ThreadPoolExecutor Worker 0 Created Worker 1 Created Worker 2 Created Worker 3 Created pool-1-thread-2 Executing 1 pool-1-thread-1 Executing 0 Worker 4 Created pool-1-thread-3 Executing 2 pool-1-thread-4 Executing 3 Worker 5 Created pool-1-thread-5 Executing 4 Worker 6 Created Worker 7 Created Worker ID: 7 is Rejected Retrying to Execute Worker ID: 7 Execution Started Worker 8 Created Worker ID: 8 is Rejected Retrying to Execute pool-2-thread-1 Executing 7 Worker ID: 8 Execution Started Worker 9 Created Worker ID: 9 is Rejected Retrying to Execute pool-2-thread-2 Executing 8 Worker ID: 9 Execution Started pool-2-thread-3 Executing 9 pool-1-thread-2 Completed 1 pool-1-thread-3 Completed 2 pool-1-thread-1 Completed 0 pool-1-thread-1 Executing 5 pool-1-thread-2 Executing 6 pool-1-thread-4 Completed 3 pool-1-thread-5 Completed 4 pool-2-thread-1 Completed 7 pool-2-thread-2 Completed 8 pool-2-thread-3 Completed 9 pool-1-thread-1 Completed 5 pool-1-thread-2 Completed 6 Execution Completed Alternate Execution Completed
2.1 Conclusion
When we submit submit a task to the ThreadPoolExecutor
then following sequence of event happens:
- If there is any worker thread free which is free and can run this task.
- Else it will try to move this task to the workerqueue from where a worker thread will pick up the task if it is free.
- If the workerQueue is also full then it will try to create a new thread if possible(no of worker threads are less than maxPoolSize).
- If all the above fails then the task is sent to the handler.
In this example the RejectedExecutionHandlerExample.java
I intentionally shutdown()
the executor
, as a result of this the executor
rejects all new tasks, which are efficiently handled using the MyRejectedExecutionHandler
. If the alternateExecutor
also fails to executor the tasks then it will throw a RejectedExecutionException
which will be caught by the catch
block in the MyRejectedExecutionHandler.java.
3. Download
It was an Example on RejectedExecutionHandler
. Download the Eclipse project of this tutorial:
You can download the full source code of this example here : RejectedExecutionHandler Example.zip