Scheduling Periodic Tasks

The ScheduledExecutorService interface provides two methods that can be used to schedule a Runnable task that should be executed periodically either after a fixed delay or at a fixed rate, with the first task execution commencing after an initial delay—in other words, scheduling periodic tasks for execution. No analogous methods are provided by the ScheduledExecutorService interface for Callable<V> tasks.

Click here to view code image

ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay,
                                          long delay, TimeUnit unit)
ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay,
                                       long period, TimeUnit unit)

The scheduleWithFixedDelay() method schedules a periodic task that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next. This means that the time interval between the start of two consecutive task executions is the sum of the execution time of the first task execution and the specified delay between them.

The scheduleAtFixedRate() method schedules a task that becomes enabled periodically for execution, with the first task execution commencing after the initial delay. This means that the time between the start of two consecutive task executions is equal to the period. Note that a new task execution commences after each period, regardless of whether or not the previous task execution has finished.

For both methods, task executions continue indefinitely, unless one of the following events occurs: The task is cancelled via the returned future, or the executor shuts down, or an exception is thrown during task execution. The isDone() method on the returned future will then return true.

Example 23.4 illustrates scheduling Runnable tasks for repeated execution using a scheduled executor service. The Runnable task to be repeatedly executed is defined at (1). It prints information at the start and just before finishing its execution, which also includes the current time, by calling the auxiliary method printTimestamp() defined at (2). In between printing the information, the Runnable task sleeps for one second.

First scheduling a periodic task to be run with a fixed delay is illustrated in the main() method. An appropriate scheduled executor service is created at (3), namely, a scheduled thread pool of size 4. The method scheduleWithFixedDelay() is called at (4), passing the task, the initial delay of one second before commencement of the first task, and a fixed delay of three seconds between the end of one task execution and the start of the next one. The main thread sleeps for 15 seconds at (5) to allow the periodic task to be scheduled and executed. And finally the scheduled executor service is shut down at (6), which will allow the executing task to complete and the executor service to terminate. Without the shutdown, the periodic task would continue to be scheduled for execution. The output from the program shows that for the fixed delay, the delay between the finishing time of a task execution and the start time of the next one is approximately three seconds as it was specified—ignoring the nanoseconds in the current time.

Analogously, the scenario above is repeated for scheduling a periodic task to be executed at a fixed rate in the main() method. A new scheduled executor service is created at (7) for this purpose. This time the method scheduleAtFixedRate() is called at (8), passing the task, the initial delay of one second before commencement of the first task, and a fixed rate of three seconds between the start of each task execution.

The main thread sleeps for 10 seconds at (9) to allow the periodic task to be executed. The shutdown() method at (10) takes care of terminating the periodic task and the executor. The output from the program shows that for the fixed rate, the time between the start time of two consecutive task executions is approximately three seconds—again, ignoring the nanoseconds in the current time.

Example 23.4 Executing Scheduled Periodic Tasks

Click here to view code image

package executors;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;
public class ScheduledPeriodicTasks {
  private static Runnable task = () -> {                                  // (1)
    printTimestamp(” Start:  I am on it!”);
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException exc) {
      System.out.println(exc);
    }
    printTimestamp(” Finish: I am not on it!”);
  };
  private static void printTimestamp(String msg) {                        // (2)
    String threadName = Thread.currentThread().getName();
    String ts = LocalTime.now().format(DateTimeFormatter.ofPattern(“HH:mm:ss”));
    System.out.println(threadName + “: ” + ts + msg);
  }
  public static void main(String[] args) {
    // Schedule a periodic task with fixed delay:
    ScheduledExecutorService ses1 = Executors.newScheduledThreadPool(4);  // (3)
    try {
      System.out.println(“Fixed delay:”);
      ses1.scheduleWithFixedDelay(task, 1, 3, TimeUnit.SECONDS);          // (4)
      TimeUnit.SECONDS.sleep(15);                                         // (5)
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      ses1.shutdown();                                                    // (6)
    }
    // Schedule a periodic task at fixed rate:
    ScheduledExecutorService ses2 = Executors.newScheduledThreadPool(4);  // (7)
    try {
      System.out.println(“\nFixed rate:”);
      ses2.scheduleAtFixedRate(task, 1, 3, TimeUnit.SECONDS);             // (8)
      TimeUnit.SECONDS.sleep(10);                                         // (9)
    } catch (InterruptedException e) {
      e.printStackTrace();

    } finally {
      ses2.shutdown();                                                    // (10)
    }
  }
}

Probable output from the program:

Click here to view code image

Fixed delay:
pool-1-thread-1: 12:55:54 Start:  I am on it!
pool-1-thread-1: 12:55:55 Finish: I am not on it!
pool-1-thread-1: 12:55:58 Start:  I am on it!
pool-1-thread-1: 12:55:59 Finish: I am not on it!
pool-1-thread-2: 12:56:02 Start:  I am on it!
pool-1-thread-2: 12:56:03 Finish: I am not on it!
pool-1-thread-1: 12:56:06 Start:  I am on it!
pool-1-thread-1: 12:56:07 Finish: I am not on it!

Fixed rate:
pool-1-thread-2: 12:56:09 Start:  I am on it!
pool-1-thread-2: 12:56:10 Finish: I am not on it!
pool-1-thread-4: 12:56:12 Start:  I am on it!
pool-1-thread-4: 12:56:13 Finish: I am not on it!
pool-1-thread-4: 12:56:15 Start:  I am on it!
pool-1-thread-4: 12:56:16 Finish: I am not on it!
pool-1-thread-4: 12:56:18 Start:  I am on it!
pool-1-thread-4: 12:56:19 Finish: I am not on it!