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.vm.Continuation;
45 import jdk.internal.vm.ScopedValueContainer;
46 import jdk.internal.vm.StackableScope;
47 import jdk.internal.vm.ThreadContainer;
48 import jdk.internal.vm.annotation.ForceInline;
49 import jdk.internal.vm.annotation.Hidden;
50 import jdk.internal.vm.annotation.IntrinsicCandidate;
51 import jdk.internal.vm.annotation.Stable;
52 import sun.nio.ch.Interruptible;
53 import sun.nio.ch.NativeThread;
54
55 import static java.util.concurrent.TimeUnit.MILLISECONDS;
56 import static java.util.concurrent.TimeUnit.NANOSECONDS;
57
58 /**
59 * A <i>thread</i> is a thread of execution in a program. The Java
60 * virtual machine allows an application to have multiple threads of
61 * execution running concurrently.
62 *
63 * <p> {@code Thread} defines constructors and a {@link Builder} to create threads.
64 * {@linkplain #start() Starting} a thread schedules it to execute its {@link #run() run}
65 * method. The newly started thread executes concurrently with the thread that caused
66 * it to start.
67 *
68 * <p> A thread <i>terminates</i> if either its {@code run} method completes normally,
69 * or if its {@code run} method completes abruptly and the appropriate {@linkplain
70 * Thread.UncaughtExceptionHandler uncaught exception handler} completes normally or
71 * abruptly. With no code left to run, the thread has completed execution. The
72 * {@link #join() join} method can be used to wait for a thread to terminate.
73 *
74 * <p> Threads have a unique {@linkplain #threadId() identifier} and a {@linkplain
163 * status and thread priority from the parent thread at the time that the child {@code
164 * Thread} is created. The {@linkplain ThreadGroup thread group} is also inherited when
165 * not provided to the constructor. When using a {@code Thread.Builder} to create a
166 * platform thread, the daemon status, thread priority, and thread group are inherited
167 * when not set on the builder. As with the constructors, inheriting from the parent
168 * thread is done when the child {@code Thread} is created.
169 *
170 * <p> A {@code Thread} inherits its initial values of {@linkplain InheritableThreadLocal
171 * inheritable-thread-local} variables (including the context class loader) from
172 * the parent thread values at the time that the child {@code Thread} is created.
173 * The 5-param {@linkplain Thread#Thread(ThreadGroup, Runnable, String, long, boolean)
174 * constructor} can be used to create a thread that does not inherit its initial
175 * values from the constructing thread. When using a {@code Thread.Builder}, the
176 * {@link Builder#inheritInheritableThreadLocals(boolean) inheritInheritableThreadLocals}
177 * method can be used to select if the initial values are inherited.
178 *
179 * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
180 * or method in this class will cause a {@link NullPointerException} to be thrown.
181 *
182 * @implNote
183 * In the JDK Reference Implementation, the following system properties may be used to
184 * configure the default virtual thread scheduler:
185 * <table class="striped">
186 * <caption style="display:none">System properties</caption>
187 * <thead>
188 * <tr>
189 * <th scope="col">System property</th>
190 * <th scope="col">Description</th>
191 * </tr>
192 * </thead>
193 * <tbody>
194 * <tr>
195 * <th scope="row">
196 * {@systemProperty jdk.virtualThreadScheduler.parallelism}
197 * </th>
198 * <td> The default scheduler's target parallelism. It defaults to the number of
199 * available processors. </td>
200 * </tr>
201 * <tr>
202 * <th scope="row">
203 * {@systemProperty jdk.virtualThreadScheduler.maxPoolSize}
204 * </th>
205 * <td> The maximum number of platform threads available to the default scheduler.
206 * It defaults to 256. </td>
207 * </tr>
208 * </tbody>
209 * </table>
210 *
211 * @since 1.0
212 */
213 public class Thread implements Runnable {
214 /* Make sure registerNatives is the first thing <clinit> does. */
215 private static native void registerNatives();
216 static {
217 registerNatives();
218 }
219
220 /*
221 * Reserved for exclusive use by the JVM. Cannot be moved to the FieldHolder
222 * as it needs to be set by the VM for JNI attaching threads, before executing
223 * the constructor that will create the FieldHolder. The historically named
224 * `eetop` holds the address of the underlying VM JavaThread, and is set to
225 * non-zero when the thread is started, and reset to zero when the thread terminates.
232
233 // thread name
234 private volatile String name;
235
236 // interrupt status (read/written by VM)
237 volatile boolean interrupted;
238
239 // context ClassLoader
240 private volatile ClassLoader contextClassLoader;
241
242 // Additional fields for platform threads.
243 // All fields, except task and terminatingThreadLocals, are accessed directly by the VM.
244 private static class FieldHolder {
245 final ThreadGroup group;
246 final Runnable task;
247 final long stackSize;
248 volatile int priority;
249 volatile boolean daemon;
250 volatile int threadStatus;
251
252 // Native thread used for signalling, set lazily, read from any thread
253 volatile NativeThread nativeThread;
254
255 // This map is maintained by the ThreadLocal class
256 ThreadLocal.ThreadLocalMap terminatingThreadLocals;
257
258 FieldHolder(ThreadGroup group,
259 Runnable task,
260 long stackSize,
261 int priority,
262 boolean daemon) {
263 this.group = group;
264 this.task = task;
265 this.stackSize = stackSize;
266 this.priority = priority;
267 if (daemon)
268 this.daemon = true;
269 }
270 }
271 private final FieldHolder holder;
272
273 ThreadLocal.ThreadLocalMap terminatingThreadLocals() {
274 return holder.terminatingThreadLocals;
275 }
276
277 void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
278 holder.terminatingThreadLocals = map;
279 }
280
281 NativeThread nativeThread() {
282 return holder.nativeThread;
283 }
284
285 void setNativeThread(NativeThread nt) {
286 holder.nativeThread = nt;
287 }
288
289 /*
290 * ThreadLocal values pertaining to this thread. This map is maintained
291 * by the ThreadLocal class.
292 */
293 private ThreadLocal.ThreadLocalMap threadLocals;
294
295 ThreadLocal.ThreadLocalMap threadLocals() {
296 return threadLocals;
297 }
298
299 void setThreadLocals(ThreadLocal.ThreadLocalMap map) {
300 threadLocals = map;
301 }
302
303 /*
304 * InheritableThreadLocal values pertaining to this thread. This map is
305 * maintained by the InheritableThreadLocal class.
306 */
307 private ThreadLocal.ThreadLocalMap inheritableThreadLocals;
308
683 static {
684 U = Unsafe.getUnsafe();
685 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
686 }
687 static long next() {
688 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
689 }
690 }
691
692 /**
693 * Initializes a platform Thread.
694 *
695 * @param g the Thread group, can be null
696 * @param name the name of the new Thread
697 * @param characteristics thread characteristics
698 * @param task the object whose run() method gets called
699 * @param stackSize the desired stack size for the new thread, or
700 * zero to indicate that this parameter is to be ignored.
701 */
702 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
703 Thread parent = currentThread();
704 boolean attached = (parent == this); // primordial or JNI attached
705
706 if (attached) {
707 if (g == null) {
708 throw new InternalError("group cannot be null when attaching");
709 }
710 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
711 } else {
712 if (g == null) {
713 // default to current thread's group
714 g = parent.getThreadGroup();
715 }
716 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
717 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
718 }
719
720 if (attached && VM.initLevel() < 1) {
721 this.tid = PRIMORDIAL_TID; // primordial thread
722 } else {
766 }
767 this.contextClassLoader = parent.getContextClassLoader();
768 } else {
769 // default CCL to the system class loader when not inheriting
770 this.contextClassLoader = ClassLoader.getSystemClassLoader();
771 }
772
773 // special value to indicate this is a newly-created Thread
774 this.scopedValueBindings = NEW_THREAD_BINDINGS;
775
776 // create a FieldHolder object, needed when bound to an OS thread
777 if (bound) {
778 ThreadGroup g = Constants.VTHREAD_GROUP;
779 int pri = NORM_PRIORITY;
780 this.holder = new FieldHolder(g, null, -1, pri, true);
781 } else {
782 this.holder = null;
783 }
784 }
785
786 /**
787 * The task {@link java.util.concurrent.Executor#execute(Runnable) submitted} to
788 * a user-provided {@link Thread.Builder.OfVirtual#scheduler(Executor) scheduler}.
789 *
790 * @apiNote The following example creates a scheduler that uses a small set of
791 * platform threads.
792 * <pre>{@code
793 * ExecutorService pool = Executors.newFixedThreadPool(4);
794 * Executor scheduler = (task) -> {
795 * // invoke pool.execute in the context of the caller
796 * pool.execute(() -> {
797 * Thread carrier = Thread.currentThread();
798 * Thread vthread = ((Thread.VirtualThreadTask) task).thread();
799 *
800 * // runs virtual thread task
801 * task.run();
802 *
803 * assert Thread.currentThread() == carrier;
804 * }));
805 * };
806 * }</pre>
807 *
808 * @see Thread.Builder.OfVirtual#scheduler(Executor)
809 * @since 99
810 */
811 public interface VirtualThreadTask extends Runnable {
812
813 /**
814 * Return the virtual thread that this task was submitted to run
815 * @return the virtual thread
816 */
817 Thread thread();
818
819 /**
820 * Attaches the given object to this task.
821 * @param att the object to attach
822 * @return the previously-attached object, if any, otherwise {@code null}
823 */
824 Object attach(Object att);
825
826 /**
827 * Retrieves the current attachment.
828 * @return the object currently attached to this task or {@code null} if
829 * there is no attachment
830 */
831 Object attachment();
832
833 /**
834 * Returns the object currently attached to the {@code VirtualThreadTask} for
835 * the current virtual thread.
836 * @return the object currently attached to current virtual thread's task
837 * @throws IllegalCallerException if the current thread is a platform thread
838 */
839 static Object currentVirtualThreadTaskAttachment() {
840 Thread t = Thread.currentThread();
841 if (t instanceof VirtualThread vthread) {
842 return vthread.currentTaskAttachment();
843 } else if (t.isVirtual()) {
844 // not supported with BoundVirtualThread
845 return null;
846 } else {
847 // platform thread
848 throw new IllegalCallerException();
849 }
850 }
851
852 /**
853 * Runs the task on the current thread as the carrier thread.
854 *
855 * <p> Invoking this method with the interrupt status set will first
856 * clear the interrupt status. Interrupting the carrier thread while
857 * running the task leads to unspecified behavior.
858 *
859 * @throws IllegalStateException if the virtual thread is not in a state to
860 * run on the current thread
861 * @throws IllegalCallerException if the current thread is a virtual thread
862 */
863 @Override
864 void run();
865 }
866
867 /**
868 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
869 * that creates platform threads.
870 *
871 * @apiNote The following are examples using the builder:
872 * {@snippet :
873 * // Start a daemon thread to run a task
874 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
875 *
876 * // Create an unstarted thread with name "duke", its start() method
877 * // must be invoked to schedule it to execute.
878 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
879 *
880 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
881 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
882 * }
883 *
884 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
885 * @since 21
886 */
1101 * that creates virtual threads.
1102 *
1103 * <p> Unless otherwise specified, passing a null argument to a method in
1104 * this interface causes a {@code NullPointerException} to be thrown.
1105 *
1106 * @see Thread#ofVirtual()
1107 * @since 21
1108 */
1109 sealed interface OfVirtual extends Builder
1110 permits ThreadBuilders.VirtualThreadBuilder {
1111
1112 @Override OfVirtual name(String name);
1113
1114 /**
1115 * @throws IllegalArgumentException {@inheritDoc}
1116 */
1117 @Override OfVirtual name(String prefix, long start);
1118
1119 @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1120 @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
1121
1122 /**
1123 * Sets the scheduler.
1124 * The thread will be scheduled by the Java virtual machine with the given
1125 * scheduler. The scheduler's {@link Executor#execute(Runnable) execute}
1126 * method is invoked with tasks of type {@link Thread.VirtualThreadTask}. It
1127 * may be invoked in the context of a virtual thread. The scheduler should
1128 * arrange to execute these tasks on a platform thread. Attempting to execute
1129 * the task on a virtual thread causes an exception to be thrown (see
1130 * {@link Thread.VirtualThreadTask#run() VirtualThreadTask.run}). The {@code
1131 * execute} method may be invoked at sensitive times (e.g. when unparking a
1132 * thread) so care should be taken to not directly execute the task on the
1133 * <em>current thread</em>.
1134 *
1135 * @param scheduler the scheduler
1136 * @return this builder
1137 * @throws UnsupportedOperationException if scheduling virtual threads to a
1138 * user-provided scheduler is not supported by this VM
1139 */
1140 @CallerSensitive
1141 @Restricted
1142 OfVirtual scheduler(Executor scheduler);
1143 }
1144 }
1145
1146 /**
1147 * Throws CloneNotSupportedException as a Thread can not be meaningfully
1148 * cloned. Construct a new Thread instead.
1149 *
1150 * @throws CloneNotSupportedException
1151 * always
1152 */
1153 @Override
1154 protected Object clone() throws CloneNotSupportedException {
1155 throw new CloneNotSupportedException();
1156 }
1157
1158 /**
1159 * Helper class for auto-numbering platform threads. The numbers start at
1160 * 0 and are separate from the thread identifier for historical reasons.
1161 */
1162 private static class ThreadNumbering {
1473 * the desired stack size for the new thread, or zero to indicate
1474 * that this parameter is to be ignored
1475 *
1476 * @param inheritInheritableThreadLocals
1477 * if {@code true}, inherit initial values for inheritable
1478 * thread-locals from the constructing thread, otherwise no initial
1479 * values are inherited
1480 *
1481 * @since 9
1482 * @see <a href="#inheritance">Inheritance when creating threads</a>
1483 */
1484 public Thread(ThreadGroup group, Runnable task, String name,
1485 long stackSize, boolean inheritInheritableThreadLocals) {
1486 this(group, checkName(name),
1487 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1488 task, stackSize);
1489 }
1490
1491 /**
1492 * Creates a virtual thread to execute a task and schedules it to execute.
1493 * The thread is scheduled to the default virtual thread scheduler.
1494 *
1495 * <p> This method is equivalent to:
1496 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1497 *
1498 * @param task the object to run when the thread executes
1499 * @return a new, and started, virtual thread
1500 * @see <a href="#inheritance">Inheritance when creating threads</a>
1501 * @since 21
1502 */
1503 public static Thread startVirtualThread(Runnable task) {
1504 Objects.requireNonNull(task);
1505 var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1506 thread.start();
1507 return thread;
1508 }
1509
1510 /**
1511 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1512 * is scheduled by the Java virtual machine rather than the operating system.
1513 *
|