-
Bug
-
Resolution: Unresolved
-
P3
-
25
-
b17
-
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 ----------
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 ----------
- caused by
-
JDK-8319447 Improve performance of delayed task handling
-
- Resolved
-