RejectedExecutionHandler Thread Pool Executor in Java Tutorial with examples

Explaining RejectedExecutionHandler

A task can be rejected as well. We need to have something in place to resolve this situation because no one would like to miss any single job in his application.

RejectedExecutionHandler is a handler for tasks that cannot be executed by a ThreadPoolExecutor.

Executors class provide simple implementation of ExecutorService using ThreadPoolExecutor but ThreadPoolExecutor provides much more feature than that. We can specify the number of threads that will be alive when we create ThreadPoolExecutor instance and we can limit the size of thread pool and create our own RejectedExecutionHandler implementation to handle the jobs that can’t fit in the worker queue.

Here is our custom implementation of RejectedExecutionHandler interface.
package com.tutorialsdesk.threads;

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor; 
public class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {   
 @Override   
 public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {  
  System.out.println(r.toString() + " is rejected");  
  }  
 } 




ThreadPoolExecutor provides several methods using which we can find out the current state of executor, pool size, active thread count and task count. So I have a monitor thread that will print the executor information at certain time interval.
package com.tutorialsdesk.threads;

import java.util.concurrent.ThreadPoolExecutor; 
public class MyMonitorThread implements Runnable {   
 private ThreadPoolExecutor executor;        
 private int seconds;        
 private boolean run=true;     
 public MyMonitorThread(ThreadPoolExecutor executor, int delay)     {  
  this.executor = executor;     
  this.seconds=delay;    
  }          
 public void shutdown(){       
  this.run=false;    
  }      
 @Override   
 public void run()     {  
  while(run){   
   System.out.println(    
     String.format("[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s",  
       this.executor.getPoolSize(),      
       this.executor.getCorePoolSize(),   
       this.executor.getActiveCount(),   
       this.executor.getCompletedTaskCount(),  
       this.executor.getTaskCount(),          
       this.executor.isShutdown(),               
       this.executor.isTerminated()));         
   try {                     Thread.sleep(seconds*1000);   
   } catch (InterruptedException e) {   
    e.printStackTrace();              
    }      
   }                 
  } 
 } 




Here is the thread pool implementation example using ThreadPoolExecutor.
package com.tutorialsdesk.threads;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadFactory; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 
public class WorkerPool {      
 public static void main(String args[]) throws InterruptedException{   
  //RejectedExecutionHandler implementation      
  RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();         
  //Get the ThreadFactory implementation to use       
  ThreadFactory threadFactory = Executors.defaultThreadFactory();  
  //creating the ThreadPoolExecutor        
  ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, rejectionHandler);        
  //start the monitoring thread         
  MyMonitorThread monitor = new MyMonitorThread(executorPool, 3);    
  Thread monitorThread = new Thread(monitor);      
  monitorThread.start();       
  //submit work to the thread pool      
  for(int i=0; i<10; i++){           
   executorPool.execute(new MyRunnable("cmd"+i));       
   }                   Thread.sleep(30000);     
   //shut down the pool         
   executorPool.shutdown();       
   //shut down the monitor thread    
   Thread.sleep(5000);         
   monitor.shutdown();          
   } 
 
 }


Notice that while initializing the ThreadPoolExecutor, we are keeping initial pool size as 2, maximum pool size to 4 and work queue size as 2. So if there are 4 running tasks and more tasks are submitted, the work queue will hold only 2 of them and rest of them will be handled by RejectedExecutionHandlerImpl.

Here is the output of above program that confirms above statement.
Command 6 is rejected
Command 7 is rejected
Command 8 is rejected
Command 9 is rejected
pool-1-thread-1 Start. Thread from Pool = Command 0
pool-1-thread-3 Start. Thread from Pool = Command 4
[monitor] [4/2] Active: 4, Completed: 0, Task: 6, isShutdown: false, isTerminated: false
pool-1-thread-2 Start. Thread from Pool = Command 1
pool-1-thread-4 Start. Thread from Pool = Command 5
pool-1-thread-1 End.
pool-1-thread-1 Start. Thread from Pool = Command 2
pool-1-thread-3 End.
pool-1-thread-3 Start. Thread from Pool = Command 3
pool-1-thread-2 End.
pool-1-thread-4 End.
pool-1-thread-3 End.
pool-1-thread-1 End.
[monitor] [4/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [4/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [4/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [2/2] Active: 0, Completed: 6, Task: 6, isShutdown: false, isTerminated: false
[monitor] [0/2] Active: 0, Completed: 6, Task: 6, isShutdown: true, isTerminated: true


Notice the change in active, completed and total completed task count of the executor. We can invoke shutdown() method to finish execution of all the submitted tasks and terminate the thread pool.

If you want to schedule a task to run with delay or periodically then you can use ScheduledThreadPoolExecutor class.

NEXT READ Future and Callable in Java.

RejectedExecutionHandler Thread Pool Executor in Java Tutorial with examples
Hope we are able to explain you Importance of RejectedExecutionHandler Thread Pool Executor in Java, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.
SHARE
    Blogger Comment
    Facebook Comment