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

Timeout passed to the CompletableFuture.get is ignored

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      MacOS 12.6 (21G115)
      Java 19.0.1

      A DESCRIPTION OF THE PROBLEM :
      Waiting on CompletableFuture.get(timeout, timeunit) can take significantly longer than the provided timeout

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the provided test code. It schedules 5 jobs on the common execution pool. Each job inside creates another job and waits for its result like this with timeout. 4 Of the jobs take 1sec for execution and 2 sec as timeout. The 5th job takes 20sec for execution and 4 sec as timeout. So the get it's supposed to finish with TimeoutException after 4sec.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Code finishes after 4 seconds because of timeout expiration
      ACTUAL -
      Code takes 20sec to finish

      ---------- BEGIN SOURCE ----------
      import java.util.ArrayList;
      import java.util.concurrent.CompletableFuture;
      import java.util.concurrent.CompletionException;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.TimeUnit;
      import java.util.concurrent.TimeoutException;
      import java.util.function.Supplier;

      public class Main {
          public static void main(String[] args) throws Exception {
              ArrayList<CompletableFuture<Boolean>> futures = new ArrayList<>();
              for (int i = 0; i <= 1; i++) {
                  futures.add(createJob(1000, 2000));
              }
              futures.add(createJob(20000, 4000));

              long start = System.currentTimeMillis();
              CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get();
              long total = System.currentTimeMillis() - start;
              System.out.println("total: " + total);

              if (total > 5000) {
                  throw new RuntimeException("total: " + total);
              }
          }

          public static CompletableFuture<Boolean> createJob(final int sleepTIme, int jobTimeout) {
              CompletableFuture<Boolean> job = CompletableFuture.supplyAsync(() -> {
                  try {
                      CompletableFuture<Boolean> finish = CompletableFuture.supplyAsync(() -> {
                          try {
                              Thread.sleep(sleepTIme);
                          } catch (InterruptedException e) {
                              throw new RuntimeException(e);
                          }
                          return false;
                      });
                      return finish.get(jobTimeout, TimeUnit.MILLISECONDS);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                      Thread.currentThread().interrupt();
                      throw new CompletionException(e);
                  } catch (ExecutionException | TimeoutException e) {
                      e.printStackTrace();
                      throw new CompletionException(e);
                  } catch (Throwable t) {
                      t.printStackTrace();
                  }
                  return true;
              });

              return job.exceptionally(e -> false);
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : often


            tongwan Andrew Wang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: