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

CompletableFuture problem in Java 25 when running on 2 or fewer cores

XMLWordPrintable

    • b17
    • 25
    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Linux running on x64 or AMD and Windows Subsystem for Linux

      Currently using Java 25+28 (but we have seen this on earlier builds of Java 25)

      A DESCRIPTION OF THE PROBLEM :
      We ran across this problem in Java 25 during our standard testing and have simplified it to work outside of our test infrastructure. It runs fine in previous versions of Java with 2 or fewer cores and runs fine in Java 25 on systems that have more than 2 cores allocated. We can reproduce locally on our Linux systems if we use taskset to limit the cores to 1 or 2.

      REGRESSION : Last worked in version 24.0.1

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test case code on a system with 1 or 2 cores (or limit the number of cores available to 1 or 2).
      For example, in Linux

      taskset -c 2-3 java Java25ThenApplyAsyncDoesNotRunOnSeparateThread.java

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I am here 1!
      I am here 2!
      I am here 3!
      I am here 4!
      I am here 5!
      I am here 6!
      ACTUAL -
      I am here 1!
      Exception in thread "main" java.util.concurrent.TimeoutException
              at java.base/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1981)
              at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2116)
              at Java25ThenApplyAsyncDoesNotRunOnSeparateThread.main(Java25ThenApplyAsyncDoesNotRunOnSeparateThread.java:33)

      ---------- BEGIN SOURCE ----------
      import java.util.concurrent.CompletableFuture;
      import java.util.concurrent.CompletionException;
      import java.util.concurrent.CountDownLatch;
      import java.util.concurrent.TimeUnit;


      public class Java25ThenApplyAsyncDoesNotRunOnSeparateThread {

          public static void main(String[] args) throws Exception {
              CountDownLatch blocker = new CountDownLatch(1);
              CompletableFuture<String> receiveSuppliedValue = new CompletableFuture<>();

              CompletableFuture<String> thenApplyAsyncCompleted = receiveSuppliedValue
                              .thenApplyAsync(value -> {
                                  return value + "Applied";
                              });

              CompletableFuture<String> supplyAsyncCompleted = CompletableFuture
                              .supplyAsync(() -> {
                                  receiveSuppliedValue.complete("Supplied");
                                  try {
                                      if (blocker.await(2, TimeUnit.MINUTES))
                                          return "supplyAsyncCompleted";
                                      else
                                          throw new RuntimeException("supplier not allowed to complete");
                                  } catch (InterruptedException x) {
                                      throw new CompletionException(x);
                                  }
                              });
               
              System.out.println("I am here 1!");
               
              String result = thenApplyAsyncCompleted.get(15, TimeUnit.SECONDS);
              System.out.println("I am here 2!");
              if (!"SuppliedApplied".equals(result)) {
                  System.err.println("Wrong value returned " + result);
                  System.exit(1);
              }
              System.out.println("I am here 3!");
              // Supplier should still be running:
              if (supplyAsyncCompleted.isDone()) {
                  System.err.println("isDone returned true when not expected to be true");
                  System.exit(1);
              }
              System.out.println("I am here 4!");
              // Allow the first bean method to complete
              blocker.countDown();
              System.out.println("I am here 5!");
              result = supplyAsyncCompleted.get(15, TimeUnit.SECONDS);
              if (!"supplyAsyncCompleted".equals(result)) {
                  System.err.println("CompletableFuture did not return expected value " + result);
                  System.exit(1);
              }
              System.out.println("I am here 6!");
          }
      }
      ---------- END SOURCE ----------

            dl Doug Lea
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: