Ad

Friday 30 August 2013

ThreadPoolExecutor - Handler Policies for Rejected Task in Java

In the previous post "ThreadPoolexecutor in Java" we created our user defined RejectedHandler,which will be invoked if any task is rejected by the ThreadPoolExecutor.In addition to defining user defined RejectedHandler,ThreadPoolExecutor provides four predefined handler polices for handling the rejected task:
  1. ThreadPoolExecutor.AbortPolicy
  2. ThreadPoolExecutor.CallerRunsPolicy
  3. ThreadPoolExecutor.DiscardPolicy
  4. ThreadPoolExecutor.DiscardOldestPolicy
If you remember the program used in the post ThreadPoolExecutor in Java we created the ThreadPool in the method createThreadPool and the user defined Rejected Handler was used in the 
ThreadPool as shown below:

private void createThreadPool() {
  int poolSize=2;
  int maxPoolSize=5;
  int queueSize=3;
  long aliveTive=1000;
  ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
  threadPoolExecutor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
                    TimeUnit.MILLISECONDS,queue,new JobRejectionHandler());
 }

When we run the program,we will get the below output.The below output shows that the rejected task 
were handled through our defined Rejection Handler  JobRejectionHandler.

Output For User defined Handler:

JobId:Job1 Running through Thread:pool-1-thread-1
JobId:Job2 Running through Thread:pool-1-thread-2
JobId:Job9 Running through RejectionHandler,Since there are no ideal threads in ThreadPool
JobId:Job10 Running through RejectionHandler,Since there are no ideal threads in ThreadPool
JobId:Job6 Running through Thread:pool-1-thread-3
JobId:Job7 Running through Thread:pool-1-thread-4
JobId:Job8 Running through Thread:pool-1-thread-5
JobId:Job3 Running through Thread:pool-1-thread-1
JobId:Job4 Running through Thread:pool-1-thread-2
JobId:Job5 Running through Thread:pool-1-thread-3

We will use the predefined handler policies while creating the ThreadPool in method createThreadPool() and will see how the output varies for each of the rejection policies.

1)ThreadPoolExecutor.AbortPolicy
    By using this handler policy in ThreadPoolExecutor,the handler will throw the exception RejectedExecutionException if any task is rejected by the Threadpool. Change the method createThreadPool() to have the ThreadPoolExecutor.AbortPolicy as the handler policy as shown below and run the program.

private void createThreadPool() {
  int poolSize=2;
  int maxPoolSize=5;
  int queueSize=3;
  long aliveTive=1000;
  ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
  threadPoolExecutor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
                TimeUnit.MILLISECONDS,queue,new ThreadPoolExecutor.AbortPolicy());
 }

Output for AbortPolicy:

JobId:Job1 Running through Thread:pool-1-thread-1
JobId:Job2 Running through Thread:pool-1-thread-2
JobId:Job6 Running through Thread:pool-1-thread-3
JobId:Job7 Running through Thread:pool-1-thread-4
Exception in thread "main" java.util.concurrent.RejectedExecutionException
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 ThreadPoolExample.submitTask(ThreadPoolExample.java:43)
at ThreadPoolExample.main(ThreadPoolExample.java:19)
JobId:Job8 Running through Thread:pool-1-thread-5
JobId:Job3 Running through Thread:pool-1-thread-1
JobId:Job4 Running through Thread:pool-1-thread-2
JobId:Job5 Running through Thread:pool-1-thread-3

As we can see in the above output the task Job9 and Job10 were rejected by the ThreadPool and hence 
the RejectedExecutionException was thrown.

2)ThreadPoolExecutor.CallerRunsPolicy
     By using this handler policy in ThreadPool,the handler will invoke the rejected task in the thread which called the execute method i.e the Caller which added this task to the ThreadPool. Change the method createThreadPool() to have the ThreadPoolExecutor.CallerRunsPolicy as the handler policy and 
run the program.This handler will slowdown the task addition to the ThreadPool if there is any rejected task since the caller(which adds the task to ThreadPool) will run the rejected task.

private void createThreadPool() {
  int poolSize=2;
  int maxPoolSize=5;
  int queueSize=3;
  long aliveTive=1000;
  ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
  threadPoolExecutor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
                TimeUnit.MILLISECONDS,queue,new ThreadPoolExecutor.CallerRunsPolicy())
 }

Output for CallerRunsPolicy:

JobId:Job1 Running through Thread:pool-1-thread-1
JobId:Job2 Running through Thread:pool-1-thread-2
JobId:Job9 Running through Thread:main
JobId:Job6 Running through Thread:pool-1-thread-3
JobId:Job7 Running through Thread:pool-1-thread-4
JobId:Job8 Running through Thread:pool-1-thread-5
JobId:Job3 Running through Thread:pool-1-thread-1
JobId:Job4 Running through Thread:pool-1-thread-2
JobId:Job5 Running through Thread:pool-1-thread-3
JobId:Job10 Running through Thread:pool-1-thread-4

As we can see in the above output the task Job9  were rejected by the ThreadPool and the handler ran 
it through the Main thread since the Main Thread is the one which added the task to the ThreadPool. Also we can notice that the task Job10 was not rejected by the ThreadPool. It is due to the slowness in adding the task to the ThreadPool,since the caller i.e Main Thread has run the rejected task Job 9 and by the time Job10 was added ,an ideal thread in the pool was found to  run the task.

3)ThreadPoolExecutor.DiscardPolicy
    This  handler will silently discards the rejected task and will not take any action for the rejected task.Change the method createThreadPool() to have the ThreadPoolExecutor.DiscardPolicy as the handler policy and run the program.

private void createThreadPool() {
  int poolSize=2;
  int maxPoolSize=5;
  int queueSize=3;
  long aliveTive=1000;
  ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
  threadPoolExecutor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
                TimeUnit.MILLISECONDS,queue,new ThreadPoolExecutor.DiscardPolicy());
 }

Output for DiscardPolicy:

JobId:Job1 Running through Thread:pool-1-thread-1
JobId:Job2 Running through Thread:pool-1-thread-2
JobId:Job6 Running through Thread:pool-1-thread-3
JobId:Job7 Running through Thread:pool-1-thread-4
JobId:Job8 Running through Thread:pool-1-thread-5
JobId:Job3 Running through Thread:pool-1-thread-1
JobId:Job4 Running through Thread:pool-1-thread-2
JobId:Job5 Running through Thread:pool-1-thread-3

As we can see in the above output the rejected task Job9 and Job10 were silently discarded by the handler and were no action taken by the handler.

4)ThreadPoolExecutor.DiscardOldestPolicy
    If any added task is about to be rejected,the handler will discards the oldest unallocated task until it finds the ideal thread and then  execute the current task through the ideal thread.Change the method createThreadPool() to have the ThreadPoolExecutor.DiscardOldestPolicy as the handler policy and run the program.

private void createThreadPool() {
  int poolSize=2;
  int maxPoolSize=5;
  int queueSize=3;
  long aliveTive=1000;
  ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
  threadPoolExecutor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
                TimeUnit.MILLISECONDS,queue,new ThreadPoolExecutor.DiscardOldestPolicy());
 }

Output for DiscardOldestPolicy:

JobId:Job1 Running through Thread:pool-1-thread-1
JobId:Job2 Running through Thread:pool-1-thread-2
JobId:Job6 Running through Thread:pool-1-thread-3
JobId:Job7 Running through Thread:pool-1-thread-4
JobId:Job8 Running through Thread:pool-1-thread-5
JobId:Job5 Running through Thread:pool-1-thread-1
JobId:Job9 Running through Thread:pool-1-thread-2
JobId:Job10 Running through Thread:pool-1-thread-3

As we can see in the above output,the ThreadPool discard the task Job 3 and Job 4.This due to:
  • Since there were no ideal threads to run the task Job9 and hence the task will handled by the handler.
  • The handler then discards the oldest unallocated task which is task Job3 waiting in the queue. Then an  ideal thread in the poolwas found to run the task Job9.
  • The same apply for Job 10 as well which made the handler to discard the oldest task Job4 and then an ideal thread was found to run the task Job10.
Related Topics:

4 comments:

  1. Very Good Tutorial,Thanks for giving proper reasons after the results

    ReplyDelete
  2. What happens if rejectedexecutedexception is caught due to the shut down of executor(Object is dereferenced). Will the behavior of handler remains same?

    ReplyDelete
  3. Is it possible to print which msg have been discarded

    ReplyDelete