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:

Saturday 24 August 2013

ThreadPoolExecutor-To write ThreadPool in Java


ThreadPoolExecutor is an implementation of ExecutorService which is used to maintain  ThreadPool for allocating and running  Threads.If we don't go for ThreadPool we wont have the control over the  no of Threads created and which will consume more system Resouces.
By using the ThreadPool we can achieve
  • Will create only the configured number of Threads
  • Will reuse the existing ideal Thread to run the Task
  • Will improve the performance and manages the System Resources well.   
So if your requirement is to run many asynchronous Task(i.e Thread),go for the ThreadPoolExecutor which manages the asynchronous task by consuming less system resources.
ThreadPoolExecutor can be created using one of its constructor as shown below

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,        
BlockingQueue<Runnable> workQueue, RejetedExecutionHandler handler)

corePoolSize

  -Minimum Number of Threads in the Pool
maxPoolSize - Maximum Number of Threads in the Pool
keepAliveTime - If the number of running threads is more than CorePoolSize,the ideal Threads will wait  for keep alivetime before terminating
unit - Timeunit for the keepAliveTime i.e MilliSeconds,Seconds or Minutes
workQueue - the queue which is used to hold any new task submitted,if the corePoolSize threads are     busy
handler - The handler to be executed,if any of the submitted task is rejected by the                  ThreadPoolExecutor

For instance lets says we create the ThreadPoolExecutor with corePoolSize as 2,queuesize as 3,maxPoolSize as 5 and keepalivetime as 1 seconds.To start with for each submitted task,Thread will be created upto corePoolSize(i.e 2) and the task will be handled.If this two threads are busy in doing some work and if a new task is submitted the task will be queueud up in the Blocking queue instead of creating a thread.If still the 2 threads are busy and  the blockingQueue is full(i.e 3),the threads  will be created upto maxpoolsize(i.e 5)  in the pool for every submitted task.If  the queue is full and still the 5 threads created (i.e maxPoolSize) are busy,for any new submitted task the task will be rejected and handled through the RejectedExecutionHandler.If  no. of threads running is more than corePoolSize and any thread is idle for 1 seconds the thread will be terminated and only the corePoolSize(i.e 2) thread will be running in pool.Thus at any time the size of the Threadpool will be between corePoolSize(ie 2) and maxPoolSize(ie 5).

To add a task to the ThreadPool,we need to use the below method of ThreadPoolExecutor

public void execute(Runnable Task)                                                                                                     

Lets see a sample code to illustate this.

import java.util.TimerTask;                                                                                                                  
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExample {

 private ThreadPoolExecutor threadPoolExecutor=null;

 public static void main(String[] args) {
  ThreadPoolExample threadPoolExample= new ThreadPoolExample();
  threadPoolExample.createThreadPool();//To create the ThreadPool
  threadPoolExample.submitTask();//To submit the 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 JobRejectionHandler());
 }

 private void submitTask()
 {
  /*Submit 10 AsunchronousTask to ThreadPool */
  for (int i=1;i<=10;i++)
  {
   threadPoolExecutor.execute(new JobTask("Job"+i));
  }
 }

 /*Asyncchrounous Task Should extend TimerTask*/
 class JobTask extends TimerTask
 {
  private String jobId="";

  public JobTask(String jobId)
  {
   this.jobId=jobId;
  }

  public String getJobId() {
   return jobId;
  }

  @Override
  public void run() {
 
   System.out.println("JobId:"+jobId+" Running through Thread:"+Thread.currentThread().getName());
   /*Make the Task to sleep for 5 seconds,so that the task will be busy*/
   try {
    Thread.sleep(5*1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
    }

/*RejectionHandler to handle any rejected Task*/
 class JobRejectionHandler implements RejectedExecutionHandler
 {

  @Override
  public void rejectedExecution(Runnable arg0, ThreadPoolExecutor arg1) {
   JobTask jobTask=(JobTask)arg0;
      System.out.println("JobId:"+jobTask.getJobId()+" Running through RejectionHandler,Since "
                   +"there are no ideal threads in ThreadPool");
  }

 }
}

Output:

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

As we can see in the above output,
  • ThreadPoolExecutor allocates Thread-1 and Thread-2 to handle task Job1 and Job2
  • Since these two threads were busy and the poolsize exceeds two(ie corePoolSize),the newly submitted task Job3,Job4 and Job5 were queued up in the BlockngQueue.
  • Since the queueSize also exceeds(i.e 3),ThreadPool creates three threads(Since maxpoolsize is 5 and already two threads were running)to handle task Job6,Job7 and Job8
  • Since the queue is also full and  the number of threads already allocated exceeds 5(i.e maxpoolsize),the submitted task Job9 and Job10 will be rejected by the ThreadPool and the corresponding rejected handler will be called
  • When any of the 5 running threads become idle,Thread pool will allocate the ideal thread to the task which are added in the Queue.Thus Job3,4 and 5 were allocated to Thread 1,2 and 3 as seen in the output.
  • when there are no task to be run and the thread become idle,the corresponding thread will be terminated i.e Thread 3,4 and 5 will be terminated after they become idle for 1 second.
  • Only two Threads Thread-1 and Thread-2 will running in the ThreadPool waiting for any incoming task.   
Related Topics :

Wednesday 21 August 2013

Servlet Life Cycle - Callback Methods

When we start the app/webserver ,the webscontainer will be loaded.Then the webcontainer will
loads the servlet and it is responsible for maintaining the servlet life cycle by calling the Servlet call back methods.The three callback methods servlet provides to the webcontainer are
  1. init()
  2. Service()
  3. destroy()

1.init()
 This method will be called only once by the webcontainer during service life cycle.Init method
provides us to write any initialization code for the servlet like creating the database connection,socket connections or loading any objects etc.Init method will be called by the container either at

  •    For the servlets which are declared as <load-on-start-up> in web.xml,Init method will be called on      Server starup.Thus the Servlet will be initiatized during the server startup.
  •    For the servlets which are not declared as <load-on-startup> in web.xml,Init method will be called      on handling the first request for the servlet.Thus the servlet will be initiatizied only this time.On          handling the Subsequent request,Init method wont be invoked.


2.Service()
Once the servlet is initialized(ie init() method is invoked),servlet is ready to handle client requests.On receiving the request for the Servlet,the container will invoke the Service method.Depending on the Value of the Http Method in the  request(ie GET/POST),doGet() or doPost()
method will be invoked from the service method.

3.destroy()
When the Servlet is about to be destroyed,Container will call the destroy() call back method of the servlet.It provides us to write any clean up code like cleaning up the database connection,socket connection etc.As we expect this destroy call back  method will be invoked on shutting down the
server.

Friday 9 August 2013

Task already scheduled or cancelled - Exception in Timer and Timer Task

While working with Timer and TimerTask,Sometime we will get the below Exception

Exception in thread "main" java.lang.IllegalStateException: Task already scheduled or cancelled
at java.util.Timer.sched(Unknown Source)
at java.util.Timer.schedule(Unknown Source)

The exception may be due to any one of the below scenario
 (1)We would have scheduled the Same Timetask object(same reference) ,which was scheduled alreadyWe  (2)would have scheduled TimerTask on the cancelled Timer
Lets see the below code example to understand this.

(1) Exception due to Scheduling the same Timer Task object reference
Lets imagine our requirement is to schedule a task to run after 15 and 25 seconds.Hence we schedule the task twice as shown below

public class TimerExample {

public static void main(String[] args) {
    TimerExample timerExample= new TimerExample();
    timerExample.timerDemoForException();
   /*Have an infinite while loop,so that Main progran wont be terminated*/ 
   while (true)
    {
   
    }
}

public void timerDemoForException()
{
Timer timer= new Timer();
Clock clock= new Clock();
timer.schedule(clock, 15*1000);//to Schedule the task to run after 15 seconds
timer.schedule(clock, 25*1000);//to Schedule the task to run after 25 seconds
}

class Clock extends TimerTask
{

@Override
public void run() {
System.out.println("Now the Tume is:"+new Date());
}
}

When we run the above program it will throw the exception "java.lang.IllegalStateException: Task already scheduled or cancelled",since we have used the same timer task object reference for scheduling twice.To resolve this,always create new Timer Task object for scheduling the Timer everytime as shown in the below code.

   public void TimerDemoForException()
{
Timer timer= new Timer();
Clock clock= new Clock();
timer.schedule(clock, 5*1000);
   clock= new Clock();//Instantiate the new Task object
timer.schedule(clock, 15*1000);
}

(2) Exception due to Scheduling the  Timer Task on cancelled Timer

For some requirement,we may like to cancel all the Scheduled Task when some condition meet.
Calling the cancel method on the Timer object,will clear all the scheduled task on the Timer object.
Thus all the scheduled task will not run and if we try to schedule any more task on the cancelled timer will throw the exception "java.lang.IllegalStateException: Timer alreadycancelled" .The below code block will show this.

 public void timerDemoForException()
{
Timer timer= new Timer();
Clock clock= new Clock();
timer.schedule(clock, 10*1000);
  timer.cancel();
  clock= new Clock();
timer.schedule(clock, 15*1000);
}

To resolve this,we need to re instantiate the timer object and then the task has to be scheduled like below code.

public void timerDemoForException()
{
Timer timer= new Timer();
Clock clock= new Clock();
timer.schedule(clock, 10*1000);
  timer.cancel();
  timer= new Timer();//Instantiate the new Timer object
  clock= new Clock();
timer.schedule(clock, 15*1000);
}

Related Topics:
Example - Timer and Timertask in Java
TimerTask - Choosing the correct Schedule Method

Thursday 8 August 2013

Timer and TimerTask in Java- An Example

In the last Post,we saw the description about each of the schedule method provided by the Timer API.
Lets start with a sample program to demonstrate how the Timer can can be used to schedule the task.

Let say our task(Job)  is to display the Current Time and need to be scheduled to run at different time.We need to write a Task for this-MyTimerTask and that should extend the Class TimerTask .The implementation(ie displaying the current Time) of the Task  has to be written in the run method.Then the task can be scheduled to run by using any of the schedule method of the Timer API depending on our requirement.

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class TimerExample {

public static void main(String[] args) {

    TimerExample timerExample= new TimerExample();
    timerExample.scheduleTimerTask();
     /*Have an Infinite while loop,so that the main program wont be terminated */
    while (true)
    {
   
    }
}

public  void scheduleTimerTask()
{
Timer timer= new Timer();
MyTimerTask timerTask=null;
Calendar calendar= Calendar.getInstance();
calendar.set(Calendar.HOUR,10);
calendar.set(Calendar.MINUTE,00);
calendar.set(Calendar.SECOND,00);
System.out.println("calendar"+calendar.getTime());

/*To Schedule the task to run once after 5 seconds*/
timerTask= new MyTimerTask("Type1");
timer.schedule(timerTask,5*1000); //

/*To Schedule the task to run once at Current Date 10:00 AM*/
timerTask= new MyTimerTask("Type2");
 timer.schedule(timerTask,calendar.getTime());

  /*Fixed Delay Execution-To Schedule the task to run repeatedly with specified
   interval of 5 seconds.First Time execution of the Task will start after 10 seconds*/
 timerTask= new MyTimerTask("Type3");
timer.schedule(timerTask,10*1000,5*1000);

/*Fixed Delay Execution-To Schedule the task to run repeatedly with specified
interval of 5 seconds.First Time execution of the Task will start at current Date 10:00 AM*/
timerTask= new MyTimerTask("Type4");
timer.schedule(timerTask,calendar.getTime(),5*1000);

/*Fixed Rate Execution-To Schedule the task to run repeatedly with specified
interval of 5 seconds.First Time execution of the Task will start at current Date 10:00 AM*/
timerTask= new MyTimerTask("Type5");
timer.scheduleAtFixedRate(timerTask,calendar.getTime(),5*1000);

/*Fixed Rate Execution-To Schedule the task to run repeatedly with specified
 interval of 5 seconds.First Time execution of the Task will start after 10 seconds*/
timerTask= new MyTimerTask("Type6");
timer.scheduleAtFixedRate(timerTask,10*1000,5*1000);
}

}

class MyTimerTask extends TimerTask
{

private String scheduleType="";
public MyTimerTask(String scheduleType)
{
this.scheduleType=scheduleType;
}

@Override
public void run() {
System.out.println("Job of Scheduled Type:"+scheduleType+" Is executed at Time:"+new Date());
}

}

Related Topics: