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
269
270 // thread name
271 private volatile String name;
272
273 // interrupted status (read/written by VM)
274 volatile boolean interrupted;
275
276 // context ClassLoader
277 private volatile ClassLoader contextClassLoader;
278
279 // Additional fields for platform threads.
280 // All fields, except task and terminatingThreadLocals, are accessed directly by the VM.
281 private static class FieldHolder {
282 final ThreadGroup group;
283 final Runnable task;
284 final long stackSize;
285 volatile int priority;
286 volatile boolean daemon;
287 volatile int threadStatus;
288
289 // This map is maintained by the ThreadLocal class
290 ThreadLocal.ThreadLocalMap terminatingThreadLocals;
291
292 FieldHolder(ThreadGroup group,
293 Runnable task,
294 long stackSize,
295 int priority,
296 boolean daemon) {
297 this.group = group;
298 this.task = task;
299 this.stackSize = stackSize;
300 this.priority = priority;
301 if (daemon)
302 this.daemon = true;
303 }
304 }
305 private final FieldHolder holder;
306
307 ThreadLocal.ThreadLocalMap terminatingThreadLocals() {
308 return holder.terminatingThreadLocals;
309 }
310
311 void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
312 holder.terminatingThreadLocals = map;
313 }
314
315 /*
316 * ThreadLocal values pertaining to this thread. This map is maintained
317 * by the ThreadLocal class.
318 */
319 private ThreadLocal.ThreadLocalMap threadLocals;
320
321 ThreadLocal.ThreadLocalMap threadLocals() {
322 return threadLocals;
323 }
324
325 void setThreadLocals(ThreadLocal.ThreadLocalMap map) {
326 threadLocals = map;
327 }
328
329 /*
330 * InheritableThreadLocal values pertaining to this thread. This map is
331 * maintained by the InheritableThreadLocal class.
332 */
333 private ThreadLocal.ThreadLocalMap inheritableThreadLocals;
334
709 static {
710 U = Unsafe.getUnsafe();
711 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
712 }
713 static long next() {
714 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
715 }
716 }
717
718 /**
719 * Initializes a platform Thread.
720 *
721 * @param g the Thread group, can be null
722 * @param name the name of the new Thread
723 * @param characteristics thread characteristics
724 * @param task the object whose run() method gets called
725 * @param stackSize the desired stack size for the new thread, or
726 * zero to indicate that this parameter is to be ignored.
727 */
728 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
729
730 Thread parent = currentThread();
731 boolean attached = (parent == this); // primordial or JNI attached
732
733 if (attached) {
734 if (g == null) {
735 throw new InternalError("group cannot be null when attaching");
736 }
737 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
738 } else {
739 if (g == null) {
740 // default to current thread's group
741 g = parent.getThreadGroup();
742 }
743 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
744 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
745 }
746
747 if (attached && VM.initLevel() < 1) {
748 this.tid = PRIMORDIAL_TID; // primordial thread
749 } else {
793 }
794 this.contextClassLoader = parent.getContextClassLoader();
795 } else {
796 // default CCL to the system class loader when not inheriting
797 this.contextClassLoader = ClassLoader.getSystemClassLoader();
798 }
799
800 // special value to indicate this is a newly-created Thread
801 this.scopedValueBindings = NEW_THREAD_BINDINGS;
802
803 // create a FieldHolder object, needed when bound to an OS thread
804 if (bound) {
805 ThreadGroup g = Constants.VTHREAD_GROUP;
806 int pri = NORM_PRIORITY;
807 this.holder = new FieldHolder(g, null, -1, pri, true);
808 } else {
809 this.holder = null;
810 }
811 }
812
813 /**
814 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
815 * that creates platform threads.
816 *
817 * @apiNote The following are examples using the builder:
818 * {@snippet :
819 * // Start a daemon thread to run a task
820 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
821 *
822 * // Create an unstarted thread with name "duke", its start() method
823 * // must be invoked to schedule it to execute.
824 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
825 *
826 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
827 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
828 * }
829 *
830 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
831 * @since 21
832 */
1047 * that creates virtual threads.
1048 *
1049 * <p> Unless otherwise specified, passing a null argument to a method in
1050 * this interface causes a {@code NullPointerException} to be thrown.
1051 *
1052 * @see Thread#ofVirtual()
1053 * @since 21
1054 */
1055 sealed interface OfVirtual extends Builder
1056 permits ThreadBuilders.VirtualThreadBuilder {
1057
1058 @Override OfVirtual name(String name);
1059
1060 /**
1061 * @throws IllegalArgumentException {@inheritDoc}
1062 */
1063 @Override OfVirtual name(String prefix, long start);
1064
1065 @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1066 @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
1067 }
1068 }
1069
1070 /**
1071 * Throws CloneNotSupportedException as a Thread can not be meaningfully
1072 * cloned. Construct a new Thread instead.
1073 *
1074 * @throws CloneNotSupportedException
1075 * always
1076 */
1077 @Override
1078 protected Object clone() throws CloneNotSupportedException {
1079 throw new CloneNotSupportedException();
1080 }
1081
1082 /**
1083 * Helper class for auto-numbering platform threads. The numbers start at
1084 * 0 and are separate from the thread identifier for historical reasons.
1085 */
1086 private static class ThreadNumbering {
1408 public Thread(ThreadGroup group, Runnable task, String name,
1409 long stackSize, boolean inheritInheritableThreadLocals) {
1410 this(group, checkName(name),
1411 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1412 task, stackSize);
1413 }
1414
1415 /**
1416 * Creates a virtual thread to execute a task and schedules it to execute.
1417 *
1418 * <p> This method is equivalent to:
1419 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1420 *
1421 * @param task the object to run when the thread executes
1422 * @return a new, and started, virtual thread
1423 * @see <a href="#inheritance">Inheritance when creating threads</a>
1424 * @since 21
1425 */
1426 public static Thread startVirtualThread(Runnable task) {
1427 Objects.requireNonNull(task);
1428 var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1429 thread.start();
1430 return thread;
1431 }
1432
1433 /**
1434 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1435 * is scheduled by the Java virtual machine rather than the operating system.
1436 *
1437 * @return {@code true} if this thread is a virtual thread
1438 *
1439 * @since 21
1440 */
1441 public final boolean isVirtual() {
1442 return (this instanceof BaseVirtualThread);
1443 }
1444
1445 /**
1446 * Schedules this thread to begin execution. The thread will execute
1447 * independently of the current thread.
1448 *
2191 * scheduled to run by the system, or has terminated.
2192 * If the returned array is of non-zero length then the first element of
2193 * the array represents the top of the stack, which is the most recent
2194 * method invocation in the sequence. The last element of the array
2195 * represents the bottom of the stack, which is the least recent method
2196 * invocation in the sequence.
2197 *
2198 * <p>Some virtual machines may, under some circumstances, omit one
2199 * or more stack frames from the stack trace. In the extreme case,
2200 * a virtual machine that has no stack trace information concerning
2201 * this thread is permitted to return a zero-length array from this
2202 * method.
2203 *
2204 * @return an array of {@code StackTraceElement},
2205 * each represents one stack frame.
2206 *
2207 * @see Throwable#getStackTrace
2208 * @since 1.5
2209 */
2210 public StackTraceElement[] getStackTrace() {
2211 if (this != Thread.currentThread()) {
2212 // optimization so we do not call into the vm for threads that
2213 // have not yet started or have terminated
2214 if (!isAlive()) {
2215 return EMPTY_STACK_TRACE;
2216 }
2217 StackTraceElement[] stackTrace = asyncGetStackTrace();
2218 return (stackTrace != null) ? stackTrace : EMPTY_STACK_TRACE;
2219 } else {
2220 return (new Exception()).getStackTrace();
2221 }
2222 }
2223
2224 /**
2225 * Returns an array of stack trace elements representing the stack dump of
2226 * this thread. Returns null if the stack trace cannot be obtained. In
2227 * the default implementation, null is returned if the thread is a virtual
2228 * thread that is not mounted or the thread is a platform thread that has
2229 * terminated.
2230 */
2231 StackTraceElement[] asyncGetStackTrace() {
2232 Object stackTrace = getStackTrace0();
2233 if (stackTrace == null) {
2234 return null;
2235 }
2236 StackTraceElement[] stes = (StackTraceElement[]) stackTrace;
2237 if (stes.length == 0) {
2238 return null;
2239 } else {
2240 return StackTraceElement.of(stes);
2241 }
2242 }
2243
2244 private native Object getStackTrace0();
2245
2246 /**
2247 * Returns a map of stack traces for all live platform threads. The map
2248 * does not include virtual threads.
2249 * The map keys are threads and each map value is an array of
2250 * {@code StackTraceElement} that represents the stack dump
2251 * of the corresponding {@code Thread}.
2252 * The returned stack traces are in the format specified for
2253 * the {@link #getStackTrace getStackTrace} method.
2254 *
2255 * <p>The threads may be executing while this method is called.
2256 * The stack trace of each thread only represents a snapshot and
2257 * each stack trace may be obtained at different time. A zero-length
2258 * array will be returned in the map value if the virtual machine has
2259 * no stack trace information about a thread.
2260 *
2261 * @return a {@code Map} from {@code Thread} to an array of
2262 * {@code StackTraceElement} that represents the stack trace of
2263 * the corresponding thread.
|
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.Future;
35 import java.util.concurrent.RejectedExecutionException;
36 import java.util.concurrent.StructureViolationException;
37 import java.util.concurrent.ThreadFactory;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.locks.LockSupport;
40 import jdk.internal.event.ThreadSleepEvent;
41 import jdk.internal.javac.Restricted;
42 import jdk.internal.misc.TerminatingThreadLocal;
43 import jdk.internal.misc.Unsafe;
44 import jdk.internal.misc.VM;
45 import jdk.internal.reflect.CallerSensitive;
46 import jdk.internal.reflect.Reflection;
47 import jdk.internal.vm.Continuation;
48 import jdk.internal.vm.ScopedValueContainer;
49 import jdk.internal.vm.StackableScope;
50 import jdk.internal.vm.ThreadContainer;
51 import jdk.internal.vm.annotation.ForceInline;
52 import jdk.internal.vm.annotation.Hidden;
53 import jdk.internal.vm.annotation.IntrinsicCandidate;
54 import jdk.internal.vm.annotation.Stable;
55 import sun.nio.ch.Interruptible;
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
275
276 // thread name
277 private volatile String name;
278
279 // interrupted status (read/written by VM)
280 volatile boolean interrupted;
281
282 // context ClassLoader
283 private volatile ClassLoader contextClassLoader;
284
285 // Additional fields for platform threads.
286 // All fields, except task and terminatingThreadLocals, are accessed directly by the VM.
287 private static class FieldHolder {
288 final ThreadGroup group;
289 final Runnable task;
290 final long stackSize;
291 volatile int priority;
292 volatile boolean daemon;
293 volatile int threadStatus;
294
295 // Used by NativeThread for signalling
296 @Stable long nativeThreadID;
297
298 // This map is maintained by the ThreadLocal class
299 ThreadLocal.ThreadLocalMap terminatingThreadLocals;
300
301 FieldHolder(ThreadGroup group,
302 Runnable task,
303 long stackSize,
304 int priority,
305 boolean daemon) {
306 this.group = group;
307 this.task = task;
308 this.stackSize = stackSize;
309 this.priority = priority;
310 if (daemon)
311 this.daemon = true;
312 }
313 }
314 private final FieldHolder holder;
315
316 ThreadLocal.ThreadLocalMap terminatingThreadLocals() {
317 return holder.terminatingThreadLocals;
318 }
319
320 void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
321 holder.terminatingThreadLocals = map;
322 }
323
324 long nativeThreadID() {
325 return holder.nativeThreadID;
326 }
327
328 void setNativeThreadID(long id) {
329 holder.nativeThreadID = id;
330 }
331
332 /*
333 * ThreadLocal values pertaining to this thread. This map is maintained
334 * by the ThreadLocal class.
335 */
336 private ThreadLocal.ThreadLocalMap threadLocals;
337
338 ThreadLocal.ThreadLocalMap threadLocals() {
339 return threadLocals;
340 }
341
342 void setThreadLocals(ThreadLocal.ThreadLocalMap map) {
343 threadLocals = map;
344 }
345
346 /*
347 * InheritableThreadLocal values pertaining to this thread. This map is
348 * maintained by the InheritableThreadLocal class.
349 */
350 private ThreadLocal.ThreadLocalMap inheritableThreadLocals;
351
726 static {
727 U = Unsafe.getUnsafe();
728 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
729 }
730 static long next() {
731 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
732 }
733 }
734
735 /**
736 * Initializes a platform Thread.
737 *
738 * @param g the Thread group, can be null
739 * @param name the name of the new Thread
740 * @param characteristics thread characteristics
741 * @param task the object whose run() method gets called
742 * @param stackSize the desired stack size for the new thread, or
743 * zero to indicate that this parameter is to be ignored.
744 */
745 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
746 Thread parent = currentThread();
747 boolean attached = (parent == this); // primordial or JNI attached
748
749 if (attached) {
750 if (g == null) {
751 throw new InternalError("group cannot be null when attaching");
752 }
753 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
754 } else {
755 if (g == null) {
756 // default to current thread's group
757 g = parent.getThreadGroup();
758 }
759 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
760 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
761 }
762
763 if (attached && VM.initLevel() < 1) {
764 this.tid = PRIMORDIAL_TID; // primordial thread
765 } else {
809 }
810 this.contextClassLoader = parent.getContextClassLoader();
811 } else {
812 // default CCL to the system class loader when not inheriting
813 this.contextClassLoader = ClassLoader.getSystemClassLoader();
814 }
815
816 // special value to indicate this is a newly-created Thread
817 this.scopedValueBindings = NEW_THREAD_BINDINGS;
818
819 // create a FieldHolder object, needed when bound to an OS thread
820 if (bound) {
821 ThreadGroup g = Constants.VTHREAD_GROUP;
822 int pri = NORM_PRIORITY;
823 this.holder = new FieldHolder(g, null, -1, pri, true);
824 } else {
825 this.holder = null;
826 }
827 }
828
829 /**
830 * The task that a {@linkplain VirtualThreadScheduler virtual thread scheduler}
831 * executes on a platform thread to
832 * {@linkplain VirtualThreadScheduler#onStart(VirtualThreadTask) start}
833 * or {@linkplain VirtualThreadScheduler#onContinue(VirtualThreadTask) continue}
834 * execution of a virtual thread. While executing the task, the platform thread is
835 * the virtual thread's <em>carrier</em>.
836 *
837 * <p> There is a {@code VirtualThreadTask} object for each virtual thread. The
838 * scheduler arranges to execute its {@link #run()} method when called to start or
839 * continue the virtual thread, if possible on the {@linkplain #preferredCarrier()
840 * preferred carrier thread}. The scheduler may attach an object to the task.
841 *
842 * @since 99
843 */
844 public sealed interface VirtualThreadTask extends Runnable permits
845 VirtualThread.BuiltinSchedulerTask, VirtualThread.CustomSchedulerTask {
846
847 /**
848 * {@return the virtual thread that this task starts or continues}
849 */
850 Thread thread();
851
852 /**
853 * Runs the task on the current thread as the carrier thread.
854 *
855 * <p> Invoking this method with the interrupted 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 * Returns the preferred carrier thread to execute this task. The scheduler may
868 * choose to ignore this preference.
869 * @return the preferred carrier thread or {@code null} if there is no preferred
870 * carrier thread
871 */
872 Thread preferredCarrier();
873
874 /**
875 * Attaches the given object to this task.
876 * @param att the object to attach
877 * @return the previously-attached object, if any, otherwise {@code null}
878 */
879 Object attach(Object att);
880
881 /**
882 * Retrieves the current attachment.
883 * @return the object currently attached to this task or {@code null} if
884 * there is no attachment
885 */
886 Object attachment();
887 }
888
889 /**
890 * Virtual thread scheduler.
891 *
892 * @apiNote The following example creates a virtual thread scheduler that uses a small
893 * set of platform threads.
894 * {@snippet lang=java :
895 * ExecutorService threadPool = Executors.newFixedThreadPool(4);
896 * var scheduler = new VirtualThreadScheduler() {
897 * private void submit(VirtualThreadTask task) {
898 * Thread caller = Thread.currentThread();
899 * threadPool.submit(() -> {
900 * Thread vthread = task.thread();
901 * Thread carrier = Thread.currentThread();
902 * try {
903 * task.run();
904 * } finally {
905 * assert Thread.currentThread() == carrier;
906 * boolean terminated = !vthread.isAlive();
907 * }
908 * });
909 * }
910 * @Override
911 * public void onStart(VirtualThreadTask task) {
912 * submit(task);
913 * }
914 * @Override
915 * public void onContinue(VirtualThreadTask task) {
916 * submit(task);
917 * }
918 * };
919 * }
920 *
921 * <p> Unless otherwise specified, passing a null argument to a method in
922 * this interface causes a {@code NullPointerException} to be thrown.
923 *
924 * @since 99
925 */
926 public interface VirtualThreadScheduler {
927 /**
928 * Invoked by {@link Thread#start()} to start execution of a {@linkplain
929 * VirtualThreadTask#thread() virtual thread}.
930 * The scheduler's implementation of this method must arrange to execute the
931 * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
932 *
933 * @implNote If invoked from a virtual thread, then the caller virtual thread is
934 * <em>pinned</em> to its carrier while executing the {@code onStart} method.
935 *
936 * @param task the task to execute
937 * @throws RejectedExecutionException if the scheduler cannot accept the task
938 */
939 void onStart(VirtualThreadTask task);
940
941 /**
942 * Invoked to continue execution of a {@linkplain VirtualThreadTask#thread()
943 * virtual thread}.
944 * The scheduler's implementation of this method must arrange to execute the
945 * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
946 *
947 * @implNote If invoked from a virtual thread, then the caller virtual thread is
948 * <em>pinned</em> to its carrier while executing the {@code onContinue} method.
949 *
950 * @param task the task to execute
951 * @throws RejectedExecutionException if the scheduler cannot accept the task
952 */
953 void onContinue(VirtualThreadTask task);
954
955 // -- prototype 1 --
956
957 /**
958 * Creates a new virtual thread, returning the {@code VirtualThreadTask} that the
959 * virtual thread scheduler arranges to execute on a platform thread to start or
960 * continue execution of the virtual thread.
961 *
962 * <p> This method creates a new unstarted {@code Thread} from the current state
963 * of the given builder to run the given task. The {@link VirtualThreadTask#thread()
964 * thread()} method returns the virtual threa. The thread's {@link Thread#start()
965 * start()} method must be invoked to schedule the thread to begin execution.
966 *
967 * @apiNote This method is intended for frameworks that make use of a custom
968 * {@link VirtualThreadScheduler VirtualThreadScheduler} and wish to specify a
969 * preferred carrier thread when creating a virtual thread, or need a reference
970 * to the virtual thread task before the virtual thread is started. The
971 * framework can use the {@link VirtualThreadTask#attach(Object) attach(Object)}
972 * method to attach its context object to the task before the thread is started.
973 *
974 * @implSpec The default implementation creates a new virtual thread. It should
975 * be rare to override this method.
976 *
977 * @param builder the virtual thread builder
978 * @param preferredCarrier the preferred carrirer, can be {@code null}
979 * @param task the object to run when the thread executes
980 * @return the {@code VirtualThreadTask} that scheduler executes
981 * @throws UnsupportedOperationException if this is the built-in default scheduler
982 *
983 * @see <a href="Thread.html#inheritance">Inheritance when creating threads</a>
984 */
985 default VirtualThreadTask newThread(Builder.OfVirtual builder,
986 Thread preferredCarrier,
987 Runnable task) {
988 Objects.requireNonNull(builder);
989 Objects.requireNonNull(task);
990 if (this == VirtualThread.builtinScheduler(false)) {
991 throw new UnsupportedOperationException();
992 }
993 var vbuilder = (ThreadBuilders.VirtualThreadBuilder) builder;
994 var vthread = (VirtualThread) vbuilder.unstarted(task, preferredCarrier);
995 return vthread.virtualThreadTask();
996 }
997
998 /**
999 * Schedules a task that becomes enabled for execution after the given delay.
1000 *
1001 * <p> This method is invoked to schedule delayed tasks in support of timed
1002 * operations and methods such as {@link Thread#sleep(long)} and {@link
1003 * Object#wait(long)}. The scheduler should arrange to execute the task on
1004 * a platform thread.
1005 *
1006 * @implSpec The default implementation schedules the task to execute after
1007 * the given delay. The task executes on JDK internal thread. An implementation
1008 * may wish to override this method when it is capable of scheduling delayed
1009 * tasks.
1010 *
1011 * @param task the task to execute
1012 * @param delay the time from now to delay execution
1013 * @param unit the time unit of the delay parameter
1014 * @return a Future representing pending completion of the task
1015 */
1016 default Future<?> schedule(Runnable task, long delay, TimeUnit unit) {
1017 return VirtualThread.DelayedTaskSchedulers.schedule(task, delay, unit);
1018 }
1019
1020 // -- prototype 2 --
1021
1022 /**
1023 * {@return the virtual thread scheduler for the current virtual thread}
1024 * @throws UnsupportedOperationException if the current thread is not a virtual
1025 * thread or scheduling virtual threads to a user-provided scheduler is not
1026 * supported by this VM
1027 */
1028 @Deprecated(forRemoval=true)
1029 @CallerSensitive
1030 @Restricted
1031 static VirtualThreadScheduler current() {
1032 if (Thread.currentThread() instanceof VirtualThread vthread) {
1033 Class<?> caller = Reflection.getCallerClass();
1034 caller.getModule().ensureNativeAccess(VirtualThreadScheduler.class,
1035 "current",
1036 caller,
1037 false);
1038 return vthread.scheduler(false);
1039 }
1040 throw new UnsupportedOperationException();
1041 }
1042 }
1043
1044 /**
1045 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
1046 * that creates platform threads.
1047 *
1048 * @apiNote The following are examples using the builder:
1049 * {@snippet :
1050 * // Start a daemon thread to run a task
1051 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
1052 *
1053 * // Create an unstarted thread with name "duke", its start() method
1054 * // must be invoked to schedule it to execute.
1055 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
1056 *
1057 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
1058 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
1059 * }
1060 *
1061 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
1062 * @since 21
1063 */
1278 * that creates virtual threads.
1279 *
1280 * <p> Unless otherwise specified, passing a null argument to a method in
1281 * this interface causes a {@code NullPointerException} to be thrown.
1282 *
1283 * @see Thread#ofVirtual()
1284 * @since 21
1285 */
1286 sealed interface OfVirtual extends Builder
1287 permits ThreadBuilders.VirtualThreadBuilder {
1288
1289 @Override OfVirtual name(String name);
1290
1291 /**
1292 * @throws IllegalArgumentException {@inheritDoc}
1293 */
1294 @Override OfVirtual name(String prefix, long start);
1295
1296 @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
1297 @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
1298
1299 // -- prototype 2 --
1300
1301 /**
1302 * Sets the scheduler.
1303 *
1304 * <p> The virtual thread will be scheduled by the Java virtual machine with
1305 * the given scheduler. The scheduler's {@link
1306 * VirtualThreadScheduler#onStart(VirtualThreadTask) onStart} and
1307 * {@link VirtualThreadScheduler#onContinue(VirtualThreadTask) onContinue}
1308 * methods may be invoked in the context of a virtual thread. The scheduler
1309 * must arrange to execute the {@link VirtualThreadTask}'s
1310 * {@code run} method on a platform thread. Attempting to execute the run
1311 * method in a virtual thread causes {@link WrongThreadException} to be thrown.
1312 * The {@code onStart} and {@code onContinue }methods may be invoked at
1313 * sensitive times (e.g. when unparking a thread) so care should be taken to
1314 * not directly execute the task on the <em>current thread</em>.
1315 *
1316 * @param scheduler the scheduler
1317 * @return this builder
1318 * @throws UnsupportedOperationException if scheduling virtual threads to a
1319 * user-provided scheduler is not supported by this VM
1320 * @since 99
1321 */
1322 @Deprecated(forRemoval=true)
1323 @CallerSensitive
1324 @Restricted
1325 OfVirtual scheduler(VirtualThreadScheduler scheduler);
1326 }
1327 }
1328
1329 /**
1330 * Throws CloneNotSupportedException as a Thread can not be meaningfully
1331 * cloned. Construct a new Thread instead.
1332 *
1333 * @throws CloneNotSupportedException
1334 * always
1335 */
1336 @Override
1337 protected Object clone() throws CloneNotSupportedException {
1338 throw new CloneNotSupportedException();
1339 }
1340
1341 /**
1342 * Helper class for auto-numbering platform threads. The numbers start at
1343 * 0 and are separate from the thread identifier for historical reasons.
1344 */
1345 private static class ThreadNumbering {
1667 public Thread(ThreadGroup group, Runnable task, String name,
1668 long stackSize, boolean inheritInheritableThreadLocals) {
1669 this(group, checkName(name),
1670 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1671 task, stackSize);
1672 }
1673
1674 /**
1675 * Creates a virtual thread to execute a task and schedules it to execute.
1676 *
1677 * <p> This method is equivalent to:
1678 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1679 *
1680 * @param task the object to run when the thread executes
1681 * @return a new, and started, virtual thread
1682 * @see <a href="#inheritance">Inheritance when creating threads</a>
1683 * @since 21
1684 */
1685 public static Thread startVirtualThread(Runnable task) {
1686 Objects.requireNonNull(task);
1687 var thread = ThreadBuilders.newVirtualThread(null, 0, task);
1688 thread.start();
1689 return thread;
1690 }
1691
1692 /**
1693 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1694 * is scheduled by the Java virtual machine rather than the operating system.
1695 *
1696 * @return {@code true} if this thread is a virtual thread
1697 *
1698 * @since 21
1699 */
1700 public final boolean isVirtual() {
1701 return (this instanceof BaseVirtualThread);
1702 }
1703
1704 /**
1705 * Schedules this thread to begin execution. The thread will execute
1706 * independently of the current thread.
1707 *
2450 * scheduled to run by the system, or has terminated.
2451 * If the returned array is of non-zero length then the first element of
2452 * the array represents the top of the stack, which is the most recent
2453 * method invocation in the sequence. The last element of the array
2454 * represents the bottom of the stack, which is the least recent method
2455 * invocation in the sequence.
2456 *
2457 * <p>Some virtual machines may, under some circumstances, omit one
2458 * or more stack frames from the stack trace. In the extreme case,
2459 * a virtual machine that has no stack trace information concerning
2460 * this thread is permitted to return a zero-length array from this
2461 * method.
2462 *
2463 * @return an array of {@code StackTraceElement},
2464 * each represents one stack frame.
2465 *
2466 * @see Throwable#getStackTrace
2467 * @since 1.5
2468 */
2469 public StackTraceElement[] getStackTrace() {
2470 if (Thread.currentThread() != this) {
2471 // optimization so we do not call into the vm for threads that
2472 // have not yet started or have terminated
2473 if (!isAlive()) {
2474 return EMPTY_STACK_TRACE;
2475 }
2476 Object trace = getStackTrace0();
2477 if (trace instanceof StackTraceElement[] stackTrace) {
2478 return StackTraceElement.finishInit(stackTrace);
2479 }
2480 return EMPTY_STACK_TRACE;
2481 } else {
2482 return (new Exception()).getStackTrace();
2483 }
2484 }
2485
2486 private native Object getStackTrace0();
2487
2488 /**
2489 * Returns a map of stack traces for all live platform threads. The map
2490 * does not include virtual threads.
2491 * The map keys are threads and each map value is an array of
2492 * {@code StackTraceElement} that represents the stack dump
2493 * of the corresponding {@code Thread}.
2494 * The returned stack traces are in the format specified for
2495 * the {@link #getStackTrace getStackTrace} method.
2496 *
2497 * <p>The threads may be executing while this method is called.
2498 * The stack trace of each thread only represents a snapshot and
2499 * each stack trace may be obtained at different time. A zero-length
2500 * array will be returned in the map value if the virtual machine has
2501 * no stack trace information about a thread.
2502 *
2503 * @return a {@code Map} from {@code Thread} to an array of
2504 * {@code StackTraceElement} that represents the stack trace of
2505 * the corresponding thread.
|