< prev index next >

src/java.base/share/classes/java/lang/Thread.java

Print this page

  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 import java.lang.ref.Reference;
  29 import java.lang.reflect.Field;
  30 import java.time.Duration;
  31 import java.util.Map;
  32 import java.util.HashMap;
  33 import java.util.Objects;


  34 import java.util.concurrent.ThreadFactory;
  35 import java.util.concurrent.StructureViolationException;
  36 import java.util.concurrent.locks.LockSupport;
  37 import jdk.internal.event.ThreadSleepEvent;

  38 import jdk.internal.misc.TerminatingThreadLocal;
  39 import jdk.internal.misc.Unsafe;
  40 import jdk.internal.misc.VM;


  41 import jdk.internal.vm.Continuation;
  42 import jdk.internal.vm.ScopedValueContainer;
  43 import jdk.internal.vm.StackableScope;
  44 import jdk.internal.vm.ThreadContainer;
  45 import jdk.internal.vm.annotation.ForceInline;
  46 import jdk.internal.vm.annotation.Hidden;
  47 import jdk.internal.vm.annotation.IntrinsicCandidate;
  48 import jdk.internal.vm.annotation.Stable;
  49 import sun.nio.ch.Interruptible;

  50 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  51 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  52 
  53 /**
  54  * A <i>thread</i> is a thread of execution in a program. The Java
  55  * virtual machine allows an application to have multiple threads of
  56  * execution running concurrently.
  57  *
  58  * <p> {@code Thread} defines constructors and a {@link Builder} to create threads.
  59  * {@linkplain #start() Starting} a thread schedules it to execute its {@link #run() run}
  60  * method. The newly started thread executes concurrently with the thread that caused
  61  * it to start.
  62  *
  63  * <p> A thread <i>terminates</i> if either its {@code run} method completes normally,
  64  * or if its {@code run} method completes abruptly and the appropriate {@linkplain
  65  * Thread.UncaughtExceptionHandler uncaught exception handler} completes normally or
  66  * abruptly. With no code left to run, the thread has completed execution. The
  67  * {@link #join() join} method can be used to wait for a thread to terminate.
  68  *
  69  * <p> Threads have a unique {@linkplain #threadId() identifier} and a {@linkplain

 158  * status and thread priority from the parent thread at the time that the child {@code
 159  * Thread} is created. The {@linkplain ThreadGroup thread group} is also inherited when
 160  * not provided to the constructor. When using a {@code Thread.Builder} to create a
 161  * platform thread, the daemon status, thread priority, and thread group are inherited
 162  * when not set on the builder. As with the constructors, inheriting from the parent
 163  * thread is done when the child {@code Thread} is created.
 164  *
 165  * <p> A {@code Thread} inherits its initial values of {@linkplain InheritableThreadLocal
 166  * inheritable-thread-local} variables (including the context class loader) from
 167  * the parent thread values at the time that the child {@code Thread} is created.
 168  * The 5-param {@linkplain Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
 169  * constructor} can be used to create a thread that does not inherit its initial
 170  * values from the constructing thread. When using a {@code Thread.Builder}, the
 171  * {@link Builder#inheritInheritableThreadLocals(boolean) inheritInheritableThreadLocals}
 172  * method can be used to select if the initial values are inherited.
 173  *
 174  * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
 175  * or method in this class will cause a {@link NullPointerException} to be thrown.
 176  *
 177  * @implNote
 178  * In the JDK Reference Implementation, the virtual thread scheduler may be configured
 179  * with the following system properties:
 180  * <table class="striped">
 181  * <caption style="display:none">System properties</caption>
 182  *   <thead>
 183  *   <tr>
 184  *     <th scope="col">System property</th>
 185  *     <th scope="col">Description</th>
 186  *   </tr>
 187  *   </thead>
 188  *   <tbody>
 189  *   <tr>
 190  *     <th scope="row">
 191  *       {@systemProperty jdk.virtualThreadScheduler.parallelism}
 192  *     </th>
 193  *     <td> The number of platform threads available for scheduling virtual
 194  *       threads. It defaults to the number of available processors. </td>
 195  *   </tr>
 196  *   <tr>
 197  *     <th scope="row">
 198  *       {@systemProperty jdk.virtualThreadScheduler.maxPoolSize}
 199  *     </th>
 200  *     <td> The maximum number of platform threads available to the scheduler.
 201  *       It defaults to 256. </td>
 202  *   </tr>
 203  *   </tbody>
 204  * </table>
 205  *
 206  * @since   1.0
 207  */
 208 public class Thread implements Runnable {
 209     /* Make sure registerNatives is the first thing <clinit> does. */
 210     private static native void registerNatives();
 211     static {
 212         registerNatives();
 213     }
 214 
 215     /*
 216      * Reserved for exclusive use by the JVM. Cannot be moved to the FieldHolder
 217      * as it needs to be set by the VM for JNI attaching threads, before executing
 218      * the constructor that will create the FieldHolder. The historically named
 219      * `eetop` holds the address of the underlying VM JavaThread, and is set to
 220      * non-zero when the thread is started, and reset to zero when the thread terminates.

 227 
 228     // thread name
 229     private volatile String name;
 230 
 231     // interrupted status (read/written by VM)
 232     volatile boolean interrupted;
 233 
 234     // context ClassLoader
 235     private volatile ClassLoader contextClassLoader;
 236 
 237     // Additional fields for platform threads.
 238     // All fields, except task and terminatingThreadLocals, are accessed directly by the VM.
 239     private static class FieldHolder {
 240         final ThreadGroup group;
 241         final Runnable task;
 242         final long stackSize;
 243         volatile int priority;
 244         volatile boolean daemon;
 245         volatile int threadStatus;
 246 



 247         // This map is maintained by the ThreadLocal class
 248         ThreadLocal.ThreadLocalMap terminatingThreadLocals;
 249 
 250         FieldHolder(ThreadGroup group,
 251                     Runnable task,
 252                     long stackSize,
 253                     int priority,
 254                     boolean daemon) {
 255             this.group = group;
 256             this.task = task;
 257             this.stackSize = stackSize;
 258             this.priority = priority;
 259             if (daemon)
 260                 this.daemon = true;
 261         }
 262     }
 263     private final FieldHolder holder;
 264 
 265     ThreadLocal.ThreadLocalMap terminatingThreadLocals() {
 266         return holder.terminatingThreadLocals;
 267     }
 268 
 269     void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
 270         holder.terminatingThreadLocals = map;
 271     }
 272 








 273     /*
 274      * ThreadLocal values pertaining to this thread. This map is maintained
 275      * by the ThreadLocal class.
 276      */
 277     private ThreadLocal.ThreadLocalMap threadLocals;
 278 
 279     ThreadLocal.ThreadLocalMap threadLocals() {
 280         return threadLocals;
 281     }
 282 
 283     void setThreadLocals(ThreadLocal.ThreadLocalMap map) {
 284         threadLocals = map;
 285     }
 286 
 287     /*
 288      * InheritableThreadLocal values pertaining to this thread. This map is
 289      * maintained by the InheritableThreadLocal class.
 290      */
 291     private ThreadLocal.ThreadLocalMap inheritableThreadLocals;
 292 

 667         static {
 668             U = Unsafe.getUnsafe();
 669             NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
 670         }
 671         static long next() {
 672             return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
 673         }
 674     }
 675 
 676     /**
 677      * Initializes a platform Thread.
 678      *
 679      * @param g the Thread group, can be null
 680      * @param name the name of the new Thread
 681      * @param characteristics thread characteristics
 682      * @param task the object whose run() method gets called
 683      * @param stackSize the desired stack size for the new thread, or
 684      *        zero to indicate that this parameter is to be ignored.
 685      */
 686     Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
 687 
 688         Thread parent = currentThread();
 689         boolean attached = (parent == this);   // primordial or JNI attached
 690 
 691         if (attached) {
 692             if (g == null) {
 693                 throw new InternalError("group cannot be null when attaching");
 694             }
 695             this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
 696         } else {
 697             if (g == null) {
 698                 // default to current thread's group
 699                 g = parent.getThreadGroup();
 700             }
 701             int priority = Math.min(parent.getPriority(), g.getMaxPriority());
 702             this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
 703         }
 704 
 705         if (attached && VM.initLevel() < 1) {
 706             this.tid = PRIMORDIAL_TID;  // primordial thread
 707         } else {

 751             }
 752             this.contextClassLoader = parent.getContextClassLoader();
 753         } else {
 754             // default CCL to the system class loader when not inheriting
 755             this.contextClassLoader = ClassLoader.getSystemClassLoader();
 756         }
 757 
 758         // special value to indicate this is a newly-created Thread
 759         this.scopedValueBindings = NEW_THREAD_BINDINGS;
 760 
 761         // create a FieldHolder object, needed when bound to an OS thread
 762         if (bound) {
 763             ThreadGroup g = Constants.VTHREAD_GROUP;
 764             int pri = NORM_PRIORITY;
 765             this.holder = new FieldHolder(g, null, -1, pri, true);
 766         } else {
 767             this.holder = null;
 768         }
 769     }
 770 































































































































































 771     /**
 772      * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
 773      * that creates platform threads.
 774      *
 775      * @apiNote The following are examples using the builder:
 776      * {@snippet :
 777      *   // Start a daemon thread to run a task
 778      *   Thread thread = Thread.ofPlatform().daemon().start(runnable);
 779      *
 780      *   // Create an unstarted thread with name "duke", its start() method
 781      *   // must be invoked to schedule it to execute.
 782      *   Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
 783      *
 784      *   // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
 785      *   ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
 786      * }
 787      *
 788      * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
 789      * @since 21
 790      */

1005          * that creates virtual threads.
1006          *
1007          * <p> Unless otherwise specified, passing a null argument to a method in
1008          * this interface causes a {@code NullPointerException} to be thrown.
1009          *
1010          * @see Thread#ofVirtual()
1011          * @since 21
1012          */
1013         sealed interface OfVirtual extends Builder
1014                 permits ThreadBuilders.VirtualThreadBuilder {
1015 
1016             @Override OfVirtual name(String name);
1017 
1018             /**
1019              * @throws IllegalArgumentException {@inheritDoc}
1020              */
1021             @Override OfVirtual name(String prefix, long start);
1022 
1023             @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1024             @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);


























1025         }
1026     }
1027 
1028     /**
1029      * Throws CloneNotSupportedException as a Thread can not be meaningfully
1030      * cloned. Construct a new Thread instead.
1031      *
1032      * @throws  CloneNotSupportedException
1033      *          always
1034      */
1035     @Override
1036     protected Object clone() throws CloneNotSupportedException {
1037         throw new CloneNotSupportedException();
1038     }
1039 
1040     /**
1041      * Helper class for auto-numbering platform threads. The numbers start at
1042      * 0 and are separate from the thread identifier for historical reasons.
1043      */
1044     private static class ThreadNumbering {

1355      *         the desired stack size for the new thread, or zero to indicate
1356      *         that this parameter is to be ignored
1357      *
1358      * @param  inheritInheritableThreadLocals
1359      *         if {@code true}, inherit initial values for inheritable
1360      *         thread-locals from the constructing thread, otherwise no initial
1361      *         values are inherited
1362      *
1363      * @since 9
1364      * @see <a href="#inheritance">Inheritance when creating threads</a>
1365      */
1366     public Thread(ThreadGroup group, Runnable task, String name,
1367                   long stackSize, boolean inheritInheritableThreadLocals) {
1368         this(group, checkName(name),
1369                 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1370                 task, stackSize);
1371     }
1372 
1373     /**
1374      * Creates a virtual thread to execute a task and schedules it to execute.

1375      *
1376      * <p> This method is equivalent to:
1377      * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1378      *
1379      * @param task the object to run when the thread executes
1380      * @return a new, and started, virtual thread
1381      * @see <a href="#inheritance">Inheritance when creating threads</a>
1382      * @since 21
1383      */
1384     public static Thread startVirtualThread(Runnable task) {
1385         Objects.requireNonNull(task);
1386         var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1387         thread.start();
1388         return thread;
1389     }
1390 
1391     /**
1392      * Returns {@code true} if this thread is a virtual thread. A virtual thread
1393      * is scheduled by the Java virtual machine rather than the operating system.
1394      *

  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 import java.lang.ref.Reference;
  29 import java.lang.reflect.Field;
  30 import java.time.Duration;
  31 import java.util.Map;
  32 import java.util.HashMap;
  33 import java.util.Objects;
  34 import java.util.concurrent.Executor;
  35 import java.util.concurrent.RejectedExecutionException;
  36 import java.util.concurrent.ThreadFactory;
  37 import java.util.concurrent.StructureViolationException;
  38 import java.util.concurrent.locks.LockSupport;
  39 import jdk.internal.event.ThreadSleepEvent;
  40 import jdk.internal.javac.Restricted;
  41 import jdk.internal.misc.TerminatingThreadLocal;
  42 import jdk.internal.misc.Unsafe;
  43 import jdk.internal.misc.VM;
  44 import jdk.internal.reflect.CallerSensitive;
  45 import jdk.internal.reflect.Reflection;
  46 import jdk.internal.vm.Continuation;
  47 import jdk.internal.vm.ScopedValueContainer;
  48 import jdk.internal.vm.StackableScope;
  49 import jdk.internal.vm.ThreadContainer;
  50 import jdk.internal.vm.annotation.ForceInline;
  51 import jdk.internal.vm.annotation.Hidden;
  52 import jdk.internal.vm.annotation.IntrinsicCandidate;
  53 import jdk.internal.vm.annotation.Stable;
  54 import sun.nio.ch.Interruptible;
  55 
  56 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  57 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  58 
  59 /**
  60  * A <i>thread</i> is a thread of execution in a program. The Java
  61  * virtual machine allows an application to have multiple threads of
  62  * execution running concurrently.
  63  *
  64  * <p> {@code Thread} defines constructors and a {@link Builder} to create threads.
  65  * {@linkplain #start() Starting} a thread schedules it to execute its {@link #run() run}
  66  * method. The newly started thread executes concurrently with the thread that caused
  67  * it to start.
  68  *
  69  * <p> A thread <i>terminates</i> if either its {@code run} method completes normally,
  70  * or if its {@code run} method completes abruptly and the appropriate {@linkplain
  71  * Thread.UncaughtExceptionHandler uncaught exception handler} completes normally or
  72  * abruptly. With no code left to run, the thread has completed execution. The
  73  * {@link #join() join} method can be used to wait for a thread to terminate.
  74  *
  75  * <p> Threads have a unique {@linkplain #threadId() identifier} and a {@linkplain

 164  * status and thread priority from the parent thread at the time that the child {@code
 165  * Thread} is created. The {@linkplain ThreadGroup thread group} is also inherited when
 166  * not provided to the constructor. When using a {@code Thread.Builder} to create a
 167  * platform thread, the daemon status, thread priority, and thread group are inherited
 168  * when not set on the builder. As with the constructors, inheriting from the parent
 169  * thread is done when the child {@code Thread} is created.
 170  *
 171  * <p> A {@code Thread} inherits its initial values of {@linkplain InheritableThreadLocal
 172  * inheritable-thread-local} variables (including the context class loader) from
 173  * the parent thread values at the time that the child {@code Thread} is created.
 174  * The 5-param {@linkplain Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
 175  * constructor} can be used to create a thread that does not inherit its initial
 176  * values from the constructing thread. When using a {@code Thread.Builder}, the
 177  * {@link Builder#inheritInheritableThreadLocals(boolean) inheritInheritableThreadLocals}
 178  * method can be used to select if the initial values are inherited.
 179  *
 180  * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
 181  * or method in this class will cause a {@link NullPointerException} to be thrown.
 182  *
 183  * @implNote
 184  * In the JDK Reference Implementation, the following system properties may be used to
 185  * configure the built-in default virtual thread scheduler:
 186  * <table class="striped">
 187  * <caption style="display:none">System properties</caption>
 188  *   <thead>
 189  *   <tr>
 190  *     <th scope="col">System property</th>
 191  *     <th scope="col">Description</th>
 192  *   </tr>
 193  *   </thead>
 194  *   <tbody>
 195  *   <tr>
 196  *     <th scope="row">
 197  *       {@systemProperty jdk.virtualThreadScheduler.parallelism}
 198  *     </th>
 199  *     <td> The default scheduler's target parallelism. It defaults to the number of
 200  *       available processors. </td>
 201  *   </tr>
 202  *   <tr>
 203  *     <th scope="row">
 204  *       {@systemProperty jdk.virtualThreadScheduler.maxPoolSize}
 205  *     </th>
 206  *     <td> The maximum number of platform threads available to the default scheduler.
 207  *       It defaults to 256. </td>
 208  *   </tr>
 209  *   </tbody>
 210  * </table>
 211  *
 212  * @since   1.0
 213  */
 214 public class Thread implements Runnable {
 215     /* Make sure registerNatives is the first thing <clinit> does. */
 216     private static native void registerNatives();
 217     static {
 218         registerNatives();
 219     }
 220 
 221     /*
 222      * Reserved for exclusive use by the JVM. Cannot be moved to the FieldHolder
 223      * as it needs to be set by the VM for JNI attaching threads, before executing
 224      * the constructor that will create the FieldHolder. The historically named
 225      * `eetop` holds the address of the underlying VM JavaThread, and is set to
 226      * non-zero when the thread is started, and reset to zero when the thread terminates.

 233 
 234     // thread name
 235     private volatile String name;
 236 
 237     // interrupted status (read/written by VM)
 238     volatile boolean interrupted;
 239 
 240     // context ClassLoader
 241     private volatile ClassLoader contextClassLoader;
 242 
 243     // Additional fields for platform threads.
 244     // All fields, except task and terminatingThreadLocals, are accessed directly by the VM.
 245     private static class FieldHolder {
 246         final ThreadGroup group;
 247         final Runnable task;
 248         final long stackSize;
 249         volatile int priority;
 250         volatile boolean daemon;
 251         volatile int threadStatus;
 252 
 253         // Used by NativeThread for signalling, set lazily, read from any thread
 254         @Stable long nativeThreadID;
 255 
 256         // This map is maintained by the ThreadLocal class
 257         ThreadLocal.ThreadLocalMap terminatingThreadLocals;
 258 
 259         FieldHolder(ThreadGroup group,
 260                     Runnable task,
 261                     long stackSize,
 262                     int priority,
 263                     boolean daemon) {
 264             this.group = group;
 265             this.task = task;
 266             this.stackSize = stackSize;
 267             this.priority = priority;
 268             if (daemon)
 269                 this.daemon = true;
 270         }
 271     }
 272     private final FieldHolder holder;
 273 
 274     ThreadLocal.ThreadLocalMap terminatingThreadLocals() {
 275         return holder.terminatingThreadLocals;
 276     }
 277 
 278     void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
 279         holder.terminatingThreadLocals = map;
 280     }
 281 
 282     long nativeThreadID() {
 283         return holder.nativeThreadID;
 284     }
 285 
 286     void setNativeThreadID(long id) {
 287         holder.nativeThreadID = id;
 288     }
 289 
 290     /*
 291      * ThreadLocal values pertaining to this thread. This map is maintained
 292      * by the ThreadLocal class.
 293      */
 294     private ThreadLocal.ThreadLocalMap threadLocals;
 295 
 296     ThreadLocal.ThreadLocalMap threadLocals() {
 297         return threadLocals;
 298     }
 299 
 300     void setThreadLocals(ThreadLocal.ThreadLocalMap map) {
 301         threadLocals = map;
 302     }
 303 
 304     /*
 305      * InheritableThreadLocal values pertaining to this thread. This map is
 306      * maintained by the InheritableThreadLocal class.
 307      */
 308     private ThreadLocal.ThreadLocalMap inheritableThreadLocals;
 309 

 684         static {
 685             U = Unsafe.getUnsafe();
 686             NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
 687         }
 688         static long next() {
 689             return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
 690         }
 691     }
 692 
 693     /**
 694      * Initializes a platform Thread.
 695      *
 696      * @param g the Thread group, can be null
 697      * @param name the name of the new Thread
 698      * @param characteristics thread characteristics
 699      * @param task the object whose run() method gets called
 700      * @param stackSize the desired stack size for the new thread, or
 701      *        zero to indicate that this parameter is to be ignored.
 702      */
 703     Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {

 704         Thread parent = currentThread();
 705         boolean attached = (parent == this);   // primordial or JNI attached
 706 
 707         if (attached) {
 708             if (g == null) {
 709                 throw new InternalError("group cannot be null when attaching");
 710             }
 711             this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
 712         } else {
 713             if (g == null) {
 714                 // default to current thread's group
 715                 g = parent.getThreadGroup();
 716             }
 717             int priority = Math.min(parent.getPriority(), g.getMaxPriority());
 718             this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
 719         }
 720 
 721         if (attached && VM.initLevel() < 1) {
 722             this.tid = PRIMORDIAL_TID;  // primordial thread
 723         } else {

 767             }
 768             this.contextClassLoader = parent.getContextClassLoader();
 769         } else {
 770             // default CCL to the system class loader when not inheriting
 771             this.contextClassLoader = ClassLoader.getSystemClassLoader();
 772         }
 773 
 774         // special value to indicate this is a newly-created Thread
 775         this.scopedValueBindings = NEW_THREAD_BINDINGS;
 776 
 777         // create a FieldHolder object, needed when bound to an OS thread
 778         if (bound) {
 779             ThreadGroup g = Constants.VTHREAD_GROUP;
 780             int pri = NORM_PRIORITY;
 781             this.holder = new FieldHolder(g, null, -1, pri, true);
 782         } else {
 783             this.holder = null;
 784         }
 785     }
 786 
 787     /**
 788      * The task that a {@linkplain VirtualThreadScheduler virtual thread scheduler}
 789      * executes on a platform thread to
 790      * {@linkplain VirtualThreadScheduler#onStart(VirtualThreadTask) start}
 791      * or {@linkplain VirtualThreadScheduler#onContinue(VirtualThreadTask) continue}
 792      * execution of a virtual thread. While executing the task, the platform thread is
 793      * the virtual thread's <em>carrier</em>.
 794      *
 795      * <p> There is a {@code VirtualThreadTask} object for each virtual thread. The
 796      * scheduler arranges to execute its {@link #run()} method when called to start or
 797      * continue the virtual thread. A scheduler may attach an object to the task.
 798      *
 799      * @since 99
 800      */
 801     public sealed interface VirtualThreadTask extends Runnable permits
 802             VirtualThread.BuiltinSchedulerTask, VirtualThread.CustomSchedulerTask {
 803 
 804         /**
 805          * {@return the virtual thread that this task starts or continues}
 806          */
 807         Thread thread();
 808 
 809         /**
 810          * Runs the task on the current thread as the carrier thread.
 811          *
 812          * <p> Invoking this method with the interrupted status set will first
 813          * clear the interrupt status. Interrupting the carrier thread while
 814          * running the task leads to unspecified behavior.
 815          *
 816          * @throws IllegalStateException if the virtual thread is not in a state to
 817          * run on the current thread
 818          * @throws IllegalCallerException if the current thread is a virtual thread
 819          */
 820         @Override
 821         void run();
 822 
 823         /**
 824          * Attaches the given object to this task.
 825          * @param att the object to attach
 826          * @return the previously-attached object, if any, otherwise {@code null}
 827          */
 828         Object attach(Object att);
 829 
 830         /**
 831          * Retrieves the current attachment.
 832          * @return the object currently attached to this task or {@code null} if
 833          * there is no attachment
 834          */
 835         Object attachment();
 836     }
 837 
 838     /**
 839      * Virtual thread scheduler.
 840      *
 841      * @apiNote The following example creates a virtual thread scheduler that uses a small
 842      * set of platform threads.
 843      * {@snippet lang=java :
 844      *     ExecutorService threadPool = Executors.newFixedThreadPool(4);
 845      *     var scheduler = new VirtualThreadScheduler() {
 846      *         private void submit(VirtualThreadTask task) {
 847      *             Thread caller = Thread.currentThread();
 848      *             threadPool.submit(() -> {
 849      *                 Thread vthread = task.thread();
 850      *                 Thread carrier = Thread.currentThread();
 851      *                 try {
 852      *                     task.run();
 853      *                 } finally {
 854      *                     assert Thread.currentThread() == carrier;
 855      *                     boolean terminated = !vthread.isAlive();
 856      *                 }
 857      *             });
 858      *         }
 859      *         @Override
 860      *         public void onStart(VirtualThreadTask task) {
 861      *             submit(task);
 862      *         }
 863      *         @Override
 864      *         public void onContinue(VirtualThreadTask task) {
 865      *             submit(task);
 866      *         }
 867      *    };
 868      * }
 869      *
 870      * <p> Unless otherwise specified, passing a null argument to a method in
 871      * this interface causes a {@code NullPointerException} to be thrown.
 872      *
 873      * @see Builder.OfVirtual#scheduler(VirtualThreadScheduler)
 874      * @since 99
 875      * @see VirtualThreadScheduler
 876      */
 877     public interface VirtualThreadScheduler {
 878         /**
 879          * Invoked by {@link Thread#start()} to start execution of a {@linkplain
 880          * VirtualThreadTask#thread() virtual thread}.
 881          * The scheduler's implementation of this method must arrange to execute the
 882          * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
 883          *
 884          * @implNote If invoked from a virtual thread, then the caller virtual thread is
 885          * <em>pinned</em> to its carrier while executing the {@code onStart} method.
 886          *
 887          * @param task the task to execute
 888          * @throws RejectedExecutionException if the scheduler cannot accept the task
 889          */
 890         void onStart(VirtualThreadTask task);
 891 
 892         /**
 893          * Invoked to continue execution of a {@linkplain VirtualThreadTask#thread()
 894          * virtual thread}.
 895          * The scheduler's implementation of this method must arrange to execute the
 896          * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
 897          *
 898          * @implNote If invoked from a virtual thread, then the caller virtual thread is
 899          * <em>pinned</em> to its carrier while executing the {@code onContinue} method.
 900          *
 901          * @param task the task to execute
 902          * @throws RejectedExecutionException if the scheduler cannot accept the task
 903          */
 904         void onContinue(VirtualThreadTask task);
 905 
 906         /**
 907          * {@return a virtual thread scheduler that delegates tasks to the given executor}
 908          * @param executor the executor
 909          */
 910         static VirtualThreadScheduler adapt(Executor executor) {
 911             Objects.requireNonNull(executor);
 912             return new VirtualThreadScheduler() {
 913                 @Override
 914                 public void onStart(VirtualThreadTask task) {
 915                     executor.execute(task);
 916                 }
 917                 @Override
 918                 public void onContinue(VirtualThreadTask task) {
 919                     executor.execute(task);
 920                 }
 921             };
 922         }
 923 
 924         /**
 925          * {@return the virtual thread scheduler for the current virtual thread}
 926          * @throws UnsupportedOperationException if the current thread is not a virtual
 927          * thread or scheduling virtual threads to a user-provided scheduler is not
 928          * supported by this VM
 929          */
 930         @CallerSensitive
 931         @Restricted
 932         static VirtualThreadScheduler current() {
 933             Class<?> caller = Reflection.getCallerClass();
 934             caller.getModule().ensureNativeAccess(VirtualThreadScheduler.class,
 935                     "current",
 936                     caller,
 937                     false);
 938             if (Thread.currentThread() instanceof VirtualThread vthread) {
 939                 return vthread.scheduler(false);
 940             } else {
 941                 throw new UnsupportedOperationException();
 942             }
 943         }
 944     }
 945 
 946     /**
 947      * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
 948      * that creates platform threads.
 949      *
 950      * @apiNote The following are examples using the builder:
 951      * {@snippet :
 952      *   // Start a daemon thread to run a task
 953      *   Thread thread = Thread.ofPlatform().daemon().start(runnable);
 954      *
 955      *   // Create an unstarted thread with name "duke", its start() method
 956      *   // must be invoked to schedule it to execute.
 957      *   Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
 958      *
 959      *   // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
 960      *   ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
 961      * }
 962      *
 963      * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
 964      * @since 21
 965      */

1180          * that creates virtual threads.
1181          *
1182          * <p> Unless otherwise specified, passing a null argument to a method in
1183          * this interface causes a {@code NullPointerException} to be thrown.
1184          *
1185          * @see Thread#ofVirtual()
1186          * @since 21
1187          */
1188         sealed interface OfVirtual extends Builder
1189                 permits ThreadBuilders.VirtualThreadBuilder {
1190 
1191             @Override OfVirtual name(String name);
1192 
1193             /**
1194              * @throws IllegalArgumentException {@inheritDoc}
1195              */
1196             @Override OfVirtual name(String prefix, long start);
1197 
1198             @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1199             @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
1200 
1201             /**
1202              * Sets the scheduler.
1203              *
1204              * <p> The virtual thread will be scheduled by the Java virtual machine with
1205              * the given scheduler. The scheduler's {@link
1206              * VirtualThreadScheduler#onStart(VirtualThreadTask) onStart} and
1207              * {@link VirtualThreadScheduler#onContinue(VirtualThreadTask) onContinue}
1208              * methods may be invoked in the context of a virtual thread. The scheduler
1209              * must arrange to execute the {@link VirtualThreadTask}'s
1210              * {@code run} method on a platform thread. Attempting to execute the run
1211              * method in a virtual thread causes {@link WrongThreadException} to be thrown.
1212              * The {@code onStart} and {@code onContinue }methods may be invoked at
1213              * sensitive times (e.g. when unparking a thread) so care should be taken to
1214              * not directly execute the task on the <em>current thread</em>.
1215              *
1216              * @param scheduler the scheduler
1217              * @return this builder
1218              * @throws UnsupportedOperationException if scheduling virtual threads to a
1219              *         user-provided scheduler is not supported by this VM
1220              *
1221              * @since 99
1222              */
1223             @CallerSensitive
1224             @Restricted
1225             OfVirtual scheduler(VirtualThreadScheduler scheduler);
1226         }
1227     }
1228 
1229     /**
1230      * Throws CloneNotSupportedException as a Thread can not be meaningfully
1231      * cloned. Construct a new Thread instead.
1232      *
1233      * @throws  CloneNotSupportedException
1234      *          always
1235      */
1236     @Override
1237     protected Object clone() throws CloneNotSupportedException {
1238         throw new CloneNotSupportedException();
1239     }
1240 
1241     /**
1242      * Helper class for auto-numbering platform threads. The numbers start at
1243      * 0 and are separate from the thread identifier for historical reasons.
1244      */
1245     private static class ThreadNumbering {

1556      *         the desired stack size for the new thread, or zero to indicate
1557      *         that this parameter is to be ignored
1558      *
1559      * @param  inheritInheritableThreadLocals
1560      *         if {@code true}, inherit initial values for inheritable
1561      *         thread-locals from the constructing thread, otherwise no initial
1562      *         values are inherited
1563      *
1564      * @since 9
1565      * @see <a href="#inheritance">Inheritance when creating threads</a>
1566      */
1567     public Thread(ThreadGroup group, Runnable task, String name,
1568                   long stackSize, boolean inheritInheritableThreadLocals) {
1569         this(group, checkName(name),
1570                 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1571                 task, stackSize);
1572     }
1573 
1574     /**
1575      * Creates a virtual thread to execute a task and schedules it to execute.
1576      * The thread is scheduled by the default virtual thread scheduler.
1577      *
1578      * <p> This method is equivalent to:
1579      * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1580      *
1581      * @param task the object to run when the thread executes
1582      * @return a new, and started, virtual thread
1583      * @see <a href="#inheritance">Inheritance when creating threads</a>
1584      * @since 21
1585      */
1586     public static Thread startVirtualThread(Runnable task) {
1587         Objects.requireNonNull(task);
1588         var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1589         thread.start();
1590         return thread;
1591     }
1592 
1593     /**
1594      * Returns {@code true} if this thread is a virtual thread. A virtual thread
1595      * is scheduled by the Java virtual machine rather than the operating system.
1596      *
< prev index next >