Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8302984

Document ScheduledExecutorService & ScheduledThreadPoolExecutor negative initial delay behavior

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      Currently it is not specified how ScheduledExecutorService and ScheduledThreadPoolExecutor, especially their `scheduleAtFixedRate` methods, handle a negative `initialDelay` value (might also be relevant for `scheduleWithFixedDelay`). The following two important questions are left unanswered:
      1. Will the task run immediately?
      2. If the task runs immediately, will the second run then have a shorter delay to make sure it still runs at the desired point in time, or will `period` be calculated based on the time when the task was scheduled instead?

      As use case let's imagine some background task which should run at 10:00 o'clock every day, and the code scheduling it calculates `initialDelay = desiredStartTime - currentTime`, so the result might be negative if it is already past 10:00 o'clock.

      The actual behavior of ScheduledThreadPoolExecutor for negative initial delay values seems to be (1) the task is run immediately and (2) the `period` is added to the current time instead of the initial delay (this could be considered a contraction to the `initialDelay + period`, ... mentioned in the documentation).
      For the background task example above this means if the task, which is supposed to run at 10:00 o'clock every day, is scheduled at 11:37 o'clock, then it will run at 11:37 o'clock every day instead.

      Below is a small example demonstrating that instead of printing "00", "10", "20", ... it prints the seconds of whatever the current time is + n * 10, e.g. "07", "17, "27", ....

      ===============
      import java.time.LocalTime;
      import java.time.ZonedDateTime;
      import java.time.format.DateTimeFormatter;
      import java.util.concurrent.ScheduledExecutorService;
      import java.util.concurrent.ScheduledThreadPoolExecutor;
      import java.util.concurrent.TimeUnit;

      class SchedulingTest {
      public static void main(String[] args) {
      ZonedDateTime startDateTime = ZonedDateTime.now().withSecond(0);
      long startDelay = startDateTime.toInstant().toEpochMilli() - System.currentTimeMillis();

      ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1);
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss");
      executor.scheduleAtFixedRate(
      () -> System.out.println(formatter.format(LocalTime.now())),
      startDelay,
      TimeUnit.SECONDS.toMillis(10),
      TimeUnit.MILLISECONDS
      );
      }
      }


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: