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 *
|