HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Java / Multi-threading / Executor RejectedExecutionHandler

Executor RejectedExecutionHandler

Learn to handle tasks which are submitted to Executor and are rejected because the executor has been shutdown for any reason using RejectedExecutionHandler.

1. When tasks get rejected

Remember when we finish the execution of an executor, we use the shutdown() method. The executor waits for the completion of tasks that are either running or waiting for their execution. Then, it shuts down the executor.

If we send a task to an executor between invoking the shutdown() method and the end of its execution, the task will be rejected. This is because the executor no longer accepts new tasks.

The ThreadPoolExecutor class provides a mechanism in form of callback method, which is called when a task is rejected.

2. RejectedExecutionHandler example

2.1. Create task to execute

Let’s create a demo task which we will execute using executor framework. This is simple task which print some statement and simulate a random delay as it is doing something important.

class Task implements Runnable 
{
	private final String name;

	public Task(String name) {
		this.name = name;
	}
	
	@Override 
    public void run() {
		System.out.printf("%s: Task %s: Created on: %s\n", 
							Thread.currentThread().getName(), 
							name, 
							LocalDateTime.now()); 
		try 
		{ 
          Long duration = (long)(Math.random()*10); 
          
          System.out.printf("%s: Task %s: Doing a task during %d seconds\n", 
	  						Thread.currentThread().getName(),
	  						name, 
	  						duration); 
          
          TimeUnit.SECONDS.sleep(duration); 
        } 
		catch (InterruptedException e) 
		{ 
          e.printStackTrace(); 
        }
		
		System.out.printf("%s: Task %s: Finished on: %s\n",
			                Thread.currentThread().getName(),
			                name,
			                LocalDateTime.now());
	}

	@Override
	public String toString() {
		return "[name=" + name + "]";
	}
}

2.2. Implement RejectedExecutionHandler

Create a class and implement interface RejectedExecutionHandler. It’s method rejectedExecution() is responsible for handling the tasks which get rejected from ThreadPoolExecutor.

class RejectedTaskHandler implements RejectedExecutionHandler 
{ 
	@Override 
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) 
	{ 
		System.out.printf("RejectedTaskHandler: The task %s has been rejected", r.toString()); 
    }
}

2.3. Add handler to executor and test it

Let’s create a executor instance and verify whether this handler is called when a thread is rejected. Here we have created a cached thread pool using the Executors.newFixedThreadPool() method in order to create the executor.

Notice we used the Runtime.availableProcessors() method that returns the number of processors available to JVM. Normally, this number matches the number of cores of the computer. Initially, thread pool will have this number of threads. In my laptop, it is 4.

After creating the executor, we send tasks of the Runnable type for execution using the execute() method.

By default, if the executor doesn’t have tasks to execute, it continues waiting for new tasks and doesn’t end its execution. JVM does not stop after all the tasks are executed. Use shutdown() method of the ThreadPoolExecutor class to indicate to the executor that we want to finish it’s execution.

After we call the shutdown() method, if we try to send another task to the executor, it will be rejected. By default, the executor will throw a RejectedExecutionException exception. If we add a RejectedExecutionHandler, then exception is not thrown and handler method is called.

This method is called for every task that is rejected by the executor.

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main 
{
	public static void main(String[] args) 
	{
		final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
				.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
		
		RejectedTaskHandler handler=new RejectedTaskHandler(); 
		
		executor.setRejectedExecutionHandler(handler); 
		
		for (int i=0; i<10; i++)
		{ 
	        Task task=new Task("Task-"+i); 
	        executor.execute(task); 
	     }
		
		//shut down the executor so that new tasks will be rejected
		executor.shutdown();
		
		Task task = new Task("Rejected task"); 
		executor.execute(task);
	}
}

Program output.

RejectedTaskHandler: The task [name=Rejected task] has been rejected

pool-1-thread-2: Task Task-1: Created on: 2019-05-22T15:13:51.147
pool-1-thread-3: Task Task-2: Created on: 2019-05-22T15:13:51.147
pool-1-thread-1: Task Task-0: Created on: 2019-05-22T15:13:51.147
pool-1-thread-1: Task Task-0: Doing a task during 6 seconds
pool-1-thread-4: Task Task-3: Created on: 2019-05-22T15:13:51.147
pool-1-thread-4: Task Task-3: Doing a task during 5 seconds
pool-1-thread-3: Task Task-2: Doing a task during 7 seconds
pool-1-thread-2: Task Task-1: Doing a task during 4 seconds
...
...
...

Clearly, the handler method of RejectedTaskHandler is invoked. Here we can add our own custom logic to handle this task as per requirements.

Drop me your questions in comments section.

Happy Learning !!

Was this post helpful?

Let us know if you liked the post. That’s the only way we can improve.

Share this:

  • Twitter
  • Facebook
  • LinkedIn
  • Reddit

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Feedback, Discussion and Comments

  1. Amit kumar Das

    January 29, 2020

    Hi I had an experiment on the program it showing ( RejectedTaskHandler: The task [name=Rejected task] has been rejected pool-1-thread-3: Task Task-2: Created on 2020-01-29T12:25:39.400) and the same task also running in console (pool-1-thread-3: Task Task-2: Doing a task during 2 seconds)

Comments are closed on this article!

Search Tutorials

Java Concurrency Tutorial

  • Java Concurrency – Introduction
  • Concurrency Evolution
  • Thread Safety
  • Concurrency vs. Parallelism
  • Compare and Swap [CAS]
  • synchronized keyword
  • Object vs. Class Level Locking
  • Runnable vs. Thread
  • wait(), notify() and notifyAll()
  • Yield() vs. Join()
  • Sleep() vs. Wait()
  • Lock vs. Monitor
  • Callable + Future
  • UncaughtExceptionHandler
  • Throttling Task Submission
  • Executor Best Practices
  • Inter-thread Communication
  • Write and Resolve Deadlock

Java Concurrency Utilities

  • AtomicInteger
  • Lock
  • ThreadFactory
  • ThreadLocal
  • ExecutorService
  • ThreadPoolExecutor
  • FixedSizeThreadPoolExecutor
  • ScheduledThreadPoolExecutor
  • Semaphore
  • Binary Semaphore
  • BlockingQueue
  • DelayQueue
  • ConcurrentLinkedDeque
  • CountDownLatch
  • ForkJoinPool

Java Tutorial

  • Java Introduction
  • Java Keywords
  • Java Flow Control
  • Java OOP
  • Java Inner Class
  • Java String
  • Java Enum
  • Java Collections
  • Java ArrayList
  • Java HashMap
  • Java Array
  • Java Sort
  • Java Clone
  • Java Date Time
  • Java Concurrency
  • Java Generics
  • Java Serialization
  • Java Input Output
  • Java New I/O
  • Java Exceptions
  • Java Annotations
  • Java Reflection
  • Java Garbage collection
  • Java JDBC
  • Java Security
  • Java Regex
  • Java Servlets
  • Java XML
  • Java Puzzles
  • Java Examples
  • Java Libraries
  • Java Resources
  • Java 14
  • Java 12
  • Java 11
  • Java 10
  • Java 9
  • Java 8
  • Java 7

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Java 15 New Features
  • Sealed Classes and Interfaces
  • EdDSA (Ed25519 / Ed448)