diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 87029dd4771..37c9cd17e02 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -968,27 +968,42 @@ public interface VirtualThreadScheduler { * @implSpec The default implementation creates a new virtual thread. It should * be rare to override this method. * - * @param builder the virtual thread builder - * @param preferredCarrier the preferred carrirer, can be {@code null} + * @param name the thread name, can be {@code null} + * @param characteristics the thread characteristics + * @param preferredCarrier the preferred carrier, can be {@code null} * @param task the object to run when the thread executes * @return the {@code VirtualThreadTask} that scheduler executes * @throws UnsupportedOperationException if this is the built-in default scheduler - * - * @see Inheritance when creating threads */ - default VirtualThreadTask newThread(Builder.OfVirtual builder, + default VirtualThreadTask newThread(String name, int characteristics, Thread preferredCarrier, Runnable task) { - Objects.requireNonNull(builder); Objects.requireNonNull(task); if (this == VirtualThread.builtinScheduler(false)) { throw new UnsupportedOperationException(); } - var vbuilder = (ThreadBuilders.VirtualThreadBuilder) builder; - var vthread = (VirtualThread) vbuilder.unstarted(task, preferredCarrier); + var vthread = new VirtualThread(this, preferredCarrier, name, characteristics, task); return vthread.virtualThreadTask(); } + /** + * Creates a new virtual thread using the given builder's configuration. + * Delegates to {@link #newThread(String, int, Thread, Runnable)}. + * + * @param builder the virtual thread builder + * @param preferredCarrier the preferred carrier, can be {@code null} + * @param task the object to run when the thread executes + * @return the {@code VirtualThreadTask} that scheduler executes + */ + default VirtualThreadTask newThread(Builder.OfVirtual builder, + Thread preferredCarrier, + Runnable task) { + Objects.requireNonNull(builder); + var vbuilder = (ThreadBuilders.VirtualThreadBuilder) builder; + return newThread(vbuilder.nextThreadName(), vbuilder.characteristics(), + preferredCarrier, task); + } + /** * Schedules a task that becomes enabled for execution after the given delay. * diff --git a/src/java.base/share/classes/java/lang/ThreadBuilders.java b/src/java.base/share/classes/java/lang/ThreadBuilders.java index 4a538f2389e..c3ed0673de0 100644 --- a/src/java.base/share/classes/java/lang/ThreadBuilders.java +++ b/src/java.base/share/classes/java/lang/ThreadBuilders.java @@ -405,12 +405,23 @@ public Thread newThread(Runnable task) { /** * Creates a new virtual thread to run the given task. */ + // true when a custom scheduler is installed via implClass, JIT constant-folds + static final boolean CUSTOM_SCHEDULER = + VirtualThread.defaultScheduler() != VirtualThread.builtinScheduler(true); + private static Thread newVirtualThread(Thread.VirtualThreadScheduler scheduler, Thread preferredCarrier, String name, int characteristics, Runnable task) { if (ContinuationSupport.isSupported()) { + // Route through the custom scheduler's newThread() when implClass is set. + // scheduler is non-null only with the legacy per-builder scheduler field, + // superseded by the global custom scheduler API (implClass). + if (scheduler == null && CUSTOM_SCHEDULER) { + return VirtualThread.defaultScheduler() + .newThread(name, characteristics, preferredCarrier, task).thread(); + } return new VirtualThread(scheduler, preferredCarrier, name, characteristics, task); } else { if (scheduler != null)