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

ScheduledExecutorService fails to execute task in scenario with Long.MAX_VALUE

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Duplicate
    • Affects Version/s: 8, 9
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_45"
      Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Darwin Macintosh-2.local 13.4.0 Darwin Kernel Version 13.4.0: Sun Aug 17 19:50:11 PDT 2014; root:xnu-2422.115.4~1/RELEASE_X86_64 x86_64

      A DESCRIPTION OF THE PROBLEM :
      Scheduling a fixed delay task with a delay of Long.MAX_VALUE always causes a previously scheduled task to never run *IF* the fixed delay task is running at the time the previously scheduled task becomes eligible to run.

      The following method can be used to illustrate the problem:

      public void runSchedulingScenario(long delayInMillis) throws InterruptedException {
          System.out.println("Running scenario for delay of " + delayInMillis);
          ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

          // schedule task to run in 1 second
          scheduledExecutorService.schedule(() -> {
              System.out.println("scheduled task with one second delay invoked");
          }, 1, TimeUnit.SECONDS);

          // schedule task to run immediately and then not again for specified delay
          // NOTE that task runs for ~two seconds and so is actively running at the
          // point the first scheduled task would be eligible for execution
          scheduledExecutorService.scheduleWithFixedDelay(() -> {
              try {
                  System.out.println("scheduled task with fixed delay invoked");
                  Thread.sleep(2000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }, 0, delayInMillis, TimeUnit.MILLISECONDS);

          System.out.println("scheduling completed");

          Thread.sleep(10000);
      }

      As seen above, the method first schedules a delayed task to execute in 1 second and then schedules a "fixed delay" task for immediate execution with the specified delay.

      The expectation is that the "fixed delay" task will execute immediately, that the task that was scheduled to execute in 1 second will become eligible to run while the "fixed delay" task is actively running, and that the task that was scheduled to execute in 1 second will execute immediately upon completion of the "fixed delay" task.

      Output from runSchedulingScenario(Integer.MAX_VALUE); is as expected:

      Running scenario for delay of 2147483647
      scheduling completed
      scheduled task with fixed delay invoked
      scheduled task with one second delay invoked

      Unexpectedly, if Long.MAX_VALUE is used as the delay, the scheduled task with one second delay is never invoked as seen from the output of runSchedulingScenario(Long.MAX_VALUE);

      Running scenario for delay of 9223372036854775807
      scheduling completed
      scheduled task with fixed delay invoked

      Additional Notes:
      1. some delay values less than Long.MAX_VALUE (eg Long.MAX_VALUE/2) also exhibit this problem
      2. some delay values greater than Integer.MAX_VALUE (eg 157784630000L) do NOT exhibit this problem
      3. if the code above is modified to remove the Thread.sleep(2000) step, then the problem never occurs

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      invoke the following method using an argument of Long.MAX_VALUE

      public void runSchedulingScenario(long delayInMillis) throws InterruptedException {
          System.out.println("Running scenario for delay of " + delayInMillis);
          ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

          // schedule task to run in 1 second
          scheduledExecutorService.schedule(() -> {
              System.out.println("scheduled task with one second delay invoked");
          }, 1, TimeUnit.SECONDS);

          // schedule task to run immediately and then not again for specified delay
          // NOTE that task runs for ~two seconds and so is actively running at the
          // point the first scheduled task would be eligible for execution
          scheduledExecutorService.scheduleWithFixedDelay(() -> {
              try {
                  System.out.println("scheduled task with fixed delay invoked");
                  Thread.sleep(2000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }, 0, delayInMillis, TimeUnit.MILLISECONDS);

          System.out.println("scheduling completed");

          Thread.sleep(10000);
      }


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Running scenario for delay of 9223372036854775807
      scheduling completed
      scheduled task with fixed delay invoked
      scheduled task with one second delay invoked
      ACTUAL -
      Running scenario for delay of 9223372036854775807
      scheduling completed
      scheduled task with fixed delay invoked

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.concurrent.Executors;
      import java.util.concurrent.ScheduledExecutorService;
      import java.util.concurrent.TimeUnit;

      public class ScheduledThreadPoolExecutorTest {

          public static void main(String[] args) {
              try {
                  runSchedulingScenario(Long.MAX_VALUE);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }

          public static void runSchedulingScenario(long delayInMillis) throws InterruptedException {
              System.out.println("Running scenario for delay of " + delayInMillis);
              ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

              // schedule task to run in 1 second
              scheduledExecutorService.schedule(() -> {
                  System.out.println("scheduled task with one second delay invoked");
              }, 1, TimeUnit.SECONDS);

              // schedule task to run immediately and then not again for specified delay
              // NOTE that task runs for ~two seconds and so is actively running at the
              // point the first scheduled task would be eligible for execution
              scheduledExecutorService.scheduleWithFixedDelay(() -> {
                  try {
                      System.out.println("scheduled task with fixed delay invoked");
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }, 0, delayInMillis, TimeUnit.MILLISECONDS);

              System.out.println("scheduling completed");

              Thread.sleep(10000);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      For the extremely rare cases where you are forced to schedule a task to run with a very long delay, using a large value like 157784630000L (5 years) is sufficient.

        Attachments

          Issue Links

            Activity

              People

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

                Dates

                Created:
                Updated:
                Resolved: