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
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 built-in 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 // Used by NativeThread for signalling, set lazily, read from any thread
253 @Stable long nativeThreadID;
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 long nativeThreadID() {
282 return holder.nativeThreadID;
283 }
284
285 void setNativeThreadID(long id) {
286 holder.nativeThreadID = id;
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 * Virtual thread scheduler.
788 *
789 * @apiNote The following example creates a virtual thread scheduler that uses a small
790 * set of platform threads.
791 * {@snippet lang=java :
792 * ExecutorService pool = Executors.newFixedThreadPool(4);
793 * VirtualThreadScheduler scheduler = (vthread, task) -> {
794 * pool.submit(() -> {
795 * Thread carrier = Thread.currentThread();
796 *
797 * // runs the virtual thread task
798 * task.run();
799 *
800 * assert Thread.currentThread() == carrier;
801 * });
802 * };
803 * }
804 *
805 * <p> Unless otherwise specified, passing a null argument to a method in
806 * this interface causes a {@code NullPointerException} to be thrown.
807 *
808 * @see Builder.OfVirtual#scheduler(VirtualThreadScheduler)
809 * @since 99
810 */
811 @FunctionalInterface
812 public interface VirtualThreadScheduler {
813 /**
814 * Continue execution of given virtual thread by executing the given task on
815 * a platform thread.
816 *
817 * @param vthread the virtual thread
818 * @param task the task to execute
819 */
820 void execute(Thread vthread, Runnable task);
821
822 /**
823 * {@return a virtual thread scheduler that delegates tasks to the given executor}
824 * @param executor the executor
825 */
826 static VirtualThreadScheduler adapt(Executor executor) {
827 Objects.requireNonNull(executor);
828 return (_, task) -> executor.execute(task);
829 }
830
831 /**
832 * {@return the virtual thread scheduler for the current virtual thread}
833 * @throws UnsupportedOperationException if the current thread is not a virtual
834 * thread or scheduling virtual threads to a user-provided scheduler is not
835 * supported by this VM
836 */
837 @CallerSensitive
838 @Restricted
839 static VirtualThreadScheduler current() {
840 Class<?> caller = Reflection.getCallerClass();
841 caller.getModule().ensureNativeAccess(VirtualThreadScheduler.class,
842 "current",
843 caller,
844 false);
845 if (Thread.currentThread() instanceof VirtualThread vthread) {
846 return vthread.scheduler(false);
847 } else {
848 throw new UnsupportedOperationException();
849 }
850 }
851 }
852
853 /**
854 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
855 * that creates platform threads.
856 *
857 * @apiNote The following are examples using the builder:
858 * {@snippet :
859 * // Start a daemon thread to run a task
860 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
861 *
862 * // Create an unstarted thread with name "duke", its start() method
863 * // must be invoked to schedule it to execute.
864 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
865 *
866 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
867 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
868 * }
869 *
870 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
871 * @since 21
872 */
1087 * that creates virtual threads.
1088 *
1089 * <p> Unless otherwise specified, passing a null argument to a method in
1090 * this interface causes a {@code NullPointerException} to be thrown.
1091 *
1092 * @see Thread#ofVirtual()
1093 * @since 21
1094 */
1095 sealed interface OfVirtual extends Builder
1096 permits ThreadBuilders.VirtualThreadBuilder {
1097
1098 @Override OfVirtual name(String name);
1099
1100 /**
1101 * @throws IllegalArgumentException {@inheritDoc}
1102 */
1103 @Override OfVirtual name(String prefix, long start);
1104
1105 @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1106 @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
1107
1108 /**
1109 * Sets the scheduler.
1110 *
1111 * The thread will be scheduled by the Java virtual machine with the given
1112 * scheduler. The scheduler's {@link VirtualThreadScheduler#execute(Thread, Runnable)}
1113 * method may be invoked in the context of a virtual thread. The scheduler
1114 * must arrange to execute the {@code Runnable}'s {@code run} method on a
1115 * platform thread. Attempting to execute the run method in a virtual thread
1116 * causes {@link WrongThreadException} to be thrown.
1117 *
1118 * The {@code execute} method may be invoked at sensitive times (e.g. when
1119 * unparking a thread) so care should be taken to not directly execute the
1120 * task on the <em>current thread</em>.
1121 *
1122 * @param scheduler the scheduler
1123 * @return this builder
1124 * @throws UnsupportedOperationException if scheduling virtual threads to a
1125 * user-provided scheduler is not supported by this VM
1126 *
1127 * @since 99
1128 */
1129 @CallerSensitive
1130 @Restricted
1131 OfVirtual scheduler(VirtualThreadScheduler scheduler);
1132 }
1133 }
1134
1135 /**
1136 * Throws CloneNotSupportedException as a Thread can not be meaningfully
1137 * cloned. Construct a new Thread instead.
1138 *
1139 * @throws CloneNotSupportedException
1140 * always
1141 */
1142 @Override
1143 protected Object clone() throws CloneNotSupportedException {
1144 throw new CloneNotSupportedException();
1145 }
1146
1147 /**
1148 * Helper class for auto-numbering platform threads. The numbers start at
1149 * 0 and are separate from the thread identifier for historical reasons.
1150 */
1151 private static class ThreadNumbering {
1462 * the desired stack size for the new thread, or zero to indicate
1463 * that this parameter is to be ignored
1464 *
1465 * @param inheritInheritableThreadLocals
1466 * if {@code true}, inherit initial values for inheritable
1467 * thread-locals from the constructing thread, otherwise no initial
1468 * values are inherited
1469 *
1470 * @since 9
1471 * @see <a href="#inheritance">Inheritance when creating threads</a>
1472 */
1473 public Thread(ThreadGroup group, Runnable task, String name,
1474 long stackSize, boolean inheritInheritableThreadLocals) {
1475 this(group, checkName(name),
1476 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1477 task, stackSize);
1478 }
1479
1480 /**
1481 * Creates a virtual thread to execute a task and schedules it to execute.
1482 * The thread is scheduled by the default virtual thread scheduler.
1483 *
1484 * <p> This method is equivalent to:
1485 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1486 *
1487 * @param task the object to run when the thread executes
1488 * @return a new, and started, virtual thread
1489 * @see <a href="#inheritance">Inheritance when creating threads</a>
1490 * @since 21
1491 */
1492 public static Thread startVirtualThread(Runnable task) {
1493 Objects.requireNonNull(task);
1494 var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1495 thread.start();
1496 return thread;
1497 }
1498
1499 /**
1500 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1501 * is scheduled by the Java virtual machine rather than the operating system.
1502 *
|