diff --git a/src/share/classes/java/util/concurrent/CompletableFuture.java b/src/share/classes/java/util/concurrent/CompletableFuture.java index 955daabedc03dadfb8ea39bd13ca7c5cd157fb54..d645bb4c39e34f9c42ee779a607f4c1e57fab581 100644 --- a/src/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/share/classes/java/util/concurrent/CompletableFuture.java @@ -421,6 +421,20 @@ public class CompletableFuture implements Future, CompletionStage { static final int ASYNC = 1; static final int NESTED = -1; + /** + * Spins before blocking in waitingGet. + * There is no need to spin on uniprocessors. + * + * Call to Runtime.availableProcessors is expensive, cache the value here. + * This unfortunately relies on the number of available CPUs during first + * initialization. This affects the case when MP system would report only + * one CPU available at startup, initialize SPINS to 0, and then make more + * CPUs online. This would incur some performance penalty due to less spins + * than would otherwise happen. + */ + private static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ? + 1 << 8 : 0); + /* ------------- Base Completion classes and operations -------------- */ @SuppressWarnings("serial") @@ -1709,8 +1723,7 @@ public class CompletableFuture implements Future, CompletionStage { Object r; while ((r = result) == null) { if (spins < 0) - spins = (Runtime.getRuntime().availableProcessors() > 1) ? - 1 << 8 : 0; // Use brief spin-wait on multiprocessors + spins = SPINS; else if (spins > 0) { if (ThreadLocalRandom.nextSecondarySeed() >= 0) --spins;