< 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     // interrupt 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.ThreadFactory;
  36 import java.util.concurrent.StructureViolationException;
  37 import java.util.concurrent.locks.LockSupport;
  38 import jdk.internal.event.ThreadSleepEvent;
  39 import jdk.internal.javac.Restricted;
  40 import jdk.internal.misc.TerminatingThreadLocal;
  41 import jdk.internal.misc.Unsafe;
  42 import jdk.internal.misc.VM;
  43 import jdk.internal.reflect.CallerSensitive;
  44 import jdk.internal.reflect.Reflection;
  45 import jdk.internal.vm.Continuation;
  46 import jdk.internal.vm.ScopedValueContainer;
  47 import jdk.internal.vm.StackableScope;
  48 import jdk.internal.vm.ThreadContainer;
  49 import jdk.internal.vm.annotation.ForceInline;
  50 import jdk.internal.vm.annotation.Hidden;
  51 import jdk.internal.vm.annotation.IntrinsicCandidate;
  52 import jdk.internal.vm.annotation.Stable;
  53 import sun.nio.ch.Interruptible;
  54 import sun.nio.ch.NativeThread;
  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     // interrupt 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         // Native thread used for signalling, set lazily, read from any thread
 254         volatile NativeThread nativeThread;
 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     NativeThread nativeThread() {
 283         return holder.nativeThread;
 284     }
 285 
 286     void setNativeThread(NativeThread nt) {
 287         holder.nativeThread = nt;
 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      * Virtual thread scheduler.
 789      *
 790      * @apiNote The following example creates a virtual thread scheduler that uses a small
 791      * set of platform threads.
 792      * {@snippet lang=java :
 793      *     ExecutorService pool = Executors.newFixedThreadPool(4);
 794      *     VirtualThreadScheduler scheduler = (vthread, task) -> {
 795      *          pool.submit(() -> {
 796      *              Thread carrier = Thread.currentThread();
 797      *
 798      *              // runs the virtual thread task
 799      *              task.run();
 800      *
 801      *              assert Thread.currentThread() == carrier;
 802      *         });
 803      *     };
 804      * }
 805      *
 806      * <p> Unless otherwise specified, passing a null argument to a method in
 807      * this interface causes a {@code NullPointerException} to be thrown.
 808      *
 809      * @see Builder.OfVirtual#scheduler(VirtualThreadScheduler)
 810      * @since 99
 811      */
 812     @FunctionalInterface
 813     public interface VirtualThreadScheduler {
 814         /**
 815          * Continue execution of given virtual thread by executing the given task on
 816          * a platform thread.
 817          *
 818          * @param vthread the virtual thread
 819          * @param task the task to execute
 820          */
 821         void execute(Thread vthread, Runnable task);
 822 
 823         /**
 824          * {@return a virtual thread scheduler that delegates tasks to the given executor}
 825          * @param executor the executor
 826          */
 827         static VirtualThreadScheduler adapt(Executor executor) {
 828             Objects.requireNonNull(executor);
 829             return (_, task) -> executor.execute(task);
 830         }
 831 
 832         /**
 833          * {@return the virtual thread scheduler for the current virtual thread}
 834          * @throws UnsupportedOperationException if the current thread is not a virtual
 835          * thread or scheduling virtual threads to a user-provided scheduler is not
 836          * supported by this VM
 837          */
 838         @CallerSensitive
 839         @Restricted
 840         static VirtualThreadScheduler current() {
 841             Class<?> caller = Reflection.getCallerClass();
 842             caller.getModule().ensureNativeAccess(VirtualThreadScheduler.class,
 843                     "current",
 844                     caller,
 845                     false);
 846             if (Thread.currentThread() instanceof VirtualThread vthread) {
 847                 return vthread.scheduler(false);
 848             } else {
 849                 throw new UnsupportedOperationException();
 850             }
 851         }
 852     }
 853 
 854     /**
 855      * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
 856      * that creates platform threads.
 857      *
 858      * @apiNote The following are examples using the builder:
 859      * {@snippet :
 860      *   // Start a daemon thread to run a task
 861      *   Thread thread = Thread.ofPlatform().daemon().start(runnable);
 862      *
 863      *   // Create an unstarted thread with name "duke", its start() method
 864      *   // must be invoked to schedule it to execute.
 865      *   Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
 866      *
 867      *   // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
 868      *   ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
 869      * }
 870      *
 871      * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
 872      * @since 21
 873      */

1088          * that creates virtual threads.
1089          *
1090          * <p> Unless otherwise specified, passing a null argument to a method in
1091          * this interface causes a {@code NullPointerException} to be thrown.
1092          *
1093          * @see Thread#ofVirtual()
1094          * @since 21
1095          */
1096         sealed interface OfVirtual extends Builder
1097                 permits ThreadBuilders.VirtualThreadBuilder {
1098 
1099             @Override OfVirtual name(String name);
1100 
1101             /**
1102              * @throws IllegalArgumentException {@inheritDoc}
1103              */
1104             @Override OfVirtual name(String prefix, long start);
1105 
1106             @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1107             @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
1108 
1109             /**
1110              * Sets the scheduler.
1111              *
1112              * The thread will be scheduled by the Java virtual machine with the given
1113              * scheduler. The scheduler's {@link VirtualThreadScheduler#execute(Thread, Runnable)}
1114              * method may be invoked in the context of a virtual thread. The scheduler
1115              * must arrange to execute the {@code Runnable}'s {@code run} method on a
1116              * platform thread. Attempting to execute the run method in a virtual thread
1117              * causes {@link WrongThreadException} to be thrown.
1118              *
1119              * The {@code execute} method may be invoked at sensitive times (e.g. when
1120              * unparking a thread) so care should be taken to not directly execute the
1121              * task on the <em>current thread</em>.
1122              *
1123              * @param scheduler the scheduler
1124              * @return this builder
1125              * @throws UnsupportedOperationException if scheduling virtual threads to a
1126              *         user-provided scheduler is not supported by this VM
1127              *
1128              * @since 99
1129              */
1130             @CallerSensitive
1131             @Restricted
1132             OfVirtual scheduler(VirtualThreadScheduler scheduler);
1133         }
1134     }
1135 
1136     /**
1137      * Throws CloneNotSupportedException as a Thread can not be meaningfully
1138      * cloned. Construct a new Thread instead.
1139      *
1140      * @throws  CloneNotSupportedException
1141      *          always
1142      */
1143     @Override
1144     protected Object clone() throws CloneNotSupportedException {
1145         throw new CloneNotSupportedException();
1146     }
1147 
1148     /**
1149      * Helper class for auto-numbering platform threads. The numbers start at
1150      * 0 and are separate from the thread identifier for historical reasons.
1151      */
1152     private static class ThreadNumbering {

1463      *         the desired stack size for the new thread, or zero to indicate
1464      *         that this parameter is to be ignored
1465      *
1466      * @param  inheritInheritableThreadLocals
1467      *         if {@code true}, inherit initial values for inheritable
1468      *         thread-locals from the constructing thread, otherwise no initial
1469      *         values are inherited
1470      *
1471      * @since 9
1472      * @see <a href="#inheritance">Inheritance when creating threads</a>
1473      */
1474     public Thread(ThreadGroup group, Runnable task, String name,
1475                   long stackSize, boolean inheritInheritableThreadLocals) {
1476         this(group, checkName(name),
1477                 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1478                 task, stackSize);
1479     }
1480 
1481     /**
1482      * Creates a virtual thread to execute a task and schedules it to execute.
1483      * The thread is scheduled to the default virtual thread scheduler.
1484      *
1485      * <p> This method is equivalent to:
1486      * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1487      *
1488      * @param task the object to run when the thread executes
1489      * @return a new, and started, virtual thread
1490      * @see <a href="#inheritance">Inheritance when creating threads</a>
1491      * @since 21
1492      */
1493     public static Thread startVirtualThread(Runnable task) {
1494         Objects.requireNonNull(task);
1495         var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1496         thread.start();
1497         return thread;
1498     }
1499 
1500     /**
1501      * Returns {@code true} if this thread is a virtual thread. A virtual thread
1502      * is scheduled by the Java virtual machine rather than the operating system.
1503      *
< prev index next >