ManagedScheduledExecutorService for Implementing Concurrency Utilities in Java EE 7 – Part 2

In my previous post you saw how to use the concurrency utilities in Java EE 7 by using the ManagedExecutorService. In this post we will have a look at a variant of this i.e the ManagedScheduledExecutorService. ManagedScheduledExecutorService is used to schedule tasks to be executed in future by specifying the delay in terms of SECONDS, MINUTES, HOURS, DAYS among others. It can be used to also submit repeating tasks which occur after certain delay. The delay can be either from the end time of the previous execution or from the start time of the previous execution.

What is ManagedScheduledExecutorService?

From the JavaDoc:

A manageable version of a ScheduledExecutorService.

A ManagedScheduledExecutorService extends the Java™ SE ScheduledExecutorService to provide methods for submitting delayed or periodic tasks for execution in a Java™ EE environment. Implementations of the ManagedScheduledExecutorService are provided by a Java™ EE Product Provider. Application Component Providers use the Java Naming and Directory Interface™ (JNDI) to look-up instances of one or more ManagedScheduledExecutorService objects using resource environment references. ManagedScheduledExecutorService instances can also be injected into application components through the use of the Resource annotation.

Following are the points of benefit from the above definition:

  1. Provides support for submitting delayed or periodic tasks
  2. Default implementation provided which can be obtained via a JNDI lookup

ManagedScheduledExecutorService builds on top of the ManagedExecutorService and provides support for scheduling tasks to be executed in future and also to submit tasks which repeat after some interval. It also provides the support provided by ManagedExecutorService. There are three ways of scheduling tasks using ManagedScheduledExecutorService:

  1. Scheduling the task once after some delay or sometime in future.
  2. Scheduling repeating tasks which occur after some time period.
  3. Scheduling repeating tasks which occur after some delay of completion of previous task.

Point 2 and 3 above are different in a very subtle way. The approach Point 2 takes is to schedule the next task after time X from the start time of the previous task i.e startTimeOfNext = startTimeOfPreviousTask + X, while in Point 3 the next task is scheduled after time X from the end time of the previous task i.e startTimeOfNext = endTimeOfPreviousTask + X.

Scheduling the task once after some delay or sometime in future

Lets look at the code first:

InitialContext ctx = new InitialContext();

//Obtaining default instance of ManagedScheduledExecutorService
ManagedScheduledExecutorService executor =
        (ManagedScheduledExecutorService) ctx
        .lookup("java:comp/DefaultManagedScheduledExecutorService");

//Noting the start time just to show that the task was scheduled later
System.out.println("Current time: "+(new Date())+"<br/>");

//Scheduling the task using the schedule() method.
//The task is created by implementing Callable interface.
ScheduledFuture<String> callableResult = executor.schedule(new Callable<String>() {

  @Override
  public String call() throws Exception {
    return "Some value returned from callback";
  }
}, 20, TimeUnit.SECONDS);

//Obtaining the result of the task execution
String result = callableResult.get();

//Showing the time at which the result was obtained.
System.out.println("Result received at: "+(new Date())+"<br/>");
System.out.println("The result received is: "+result);

In the above code we

  1. Obtain the instance of ManagedShceduledExecutorSerivce using JNDI lookup.
  2. Schedule a task using the schedule() method. The task here is an implementation of Callable interface.
  3. Get the result returned from the task.

You can include the above code in any servlet and try it out. The expected output will be:

INFO:   Current time: Wed Oct 30 23:09:32 IST 2013<br/>
INFO:   Result received at: Wed Oct 30 23:09:52 IST 2013<br/>
INFO:   The result received is: Some value returned from callback

Scheduling repeating tasks which occur after some time period

Lets look at the code:

InitialContext ctx = new InitialContext();

//Obtain the default instance of ManagedScheduledExecutorService
ManagedScheduledExecutorService executor =
        (ManagedScheduledExecutorService) ctx
        .lookup("java:comp/DefaultManagedScheduledExecutorService");

//Schedule a task at fixed interval/rate using the scheduleAtFixedRate.
//Here a task is an implementation of Runnable interface.
//Here the value 3 represents the initial delay i.e the first task will be fired after 3 seconds.
//Here the value 2 represents the time duration between subsequent tasks is 2 seconds.
executor.scheduleAtFixedRate(new Runnable() {

  @Override
  public void run() {
    System.out.println("Runnable task has been invoked");
  }
}, 3,2, TimeUnit.SECONDS).get();

In the above code we have used the method scheduleAtFixedRate() to submit repeating task. The task here is an implementation of Runnable interface. There are 4 parameters to the scheduleAtFixedRate method and they are in order from left to right:

  1. The task to be repeated – implementation of Runnable interface.
  2. The initial delay after which the first task is submitted.
  3. The time difference between the start times of subsequent tasks.
  4. The unit in which the time delays ( i.e in Point 2,3) are specified.

Scheduling repeating tasks which occur after some delay of completion of previous task

There is a subtle difference between using scheduleAtFixedRate() i.e to schedule repeating tasks which occur after certain fixed time and using scheduleWithFixedDelay() i.e to schedule repeating tasks which occur after certain delay from the point the previous execution of the task is completed. Lets look at the code:

InitialContext ctx = new InitialContext();
ManagedScheduledExecutorService executor =
        (ManagedScheduledExecutorService) ctx
        .lookup("java:comp/DefaultManagedScheduledExecutorService");

executor.scheduleWithFixedDelay(new Runnable() {

  @Override
  public void run() {
    System.out.println("Runnable task has been invoked");
  }
}, 3,2, TimeUnit.SECONDS).get();

The above code is exactly similar to the one give before this i.e which uses scheduleAtFixedRate() method. The only difference is the 3rd parameter to the scheduleWithFixedDelay() method which indicates the time delay between end time of previous execution and the start time of the next execution.

Comments

comments

About Mohamed Sanaulla

In his day job he works on developing enterprise applications using ADF. He is also the moderator of JavaRanch forums and an avid blogger.

Speak Your Mind

*