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
720 static {
721 U = Unsafe.getUnsafe();
722 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
723 }
724 static long next() {
725 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
726 }
727 }
728
729 /**
730 * Initializes a platform Thread.
731 *
732 * @param g the Thread group, can be null
733 * @param name the name of the new Thread
734 * @param characteristics thread characteristics
735 * @param task the object whose run() method gets called
736 * @param stackSize the desired stack size for the new thread, or
737 * zero to indicate that this parameter is to be ignored.
738 */
739 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
740
741 Thread parent = currentThread();
742 boolean attached = (parent == this); // primordial or JNI attached
743
744 if (attached) {
745 if (g == null) {
746 throw new InternalError("group cannot be null when attaching");
747 }
748 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
749 } else {
750 if (g == null) {
751 // default to current thread's group
752 g = parent.getThreadGroup();
753 }
754 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
755 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
756 }
757
758 if (attached && VM.initLevel() < 1) {
759 this.tid = PRIMORDIAL_TID; // primordial thread
760 } else {
804 }
805 this.contextClassLoader = parent.getContextClassLoader();
806 } else {
807 // default CCL to the system class loader when not inheriting
808 this.contextClassLoader = ClassLoader.getSystemClassLoader();
809 }
810
811 // special value to indicate this is a newly-created Thread
812 this.scopedValueBindings = NEW_THREAD_BINDINGS;
813
814 // create a FieldHolder object, needed when bound to an OS thread
815 if (bound) {
816 ThreadGroup g = Constants.VTHREAD_GROUP;
817 int pri = NORM_PRIORITY;
818 this.holder = new FieldHolder(g, null, -1, pri, true);
819 } else {
820 this.holder = null;
821 }
822 }
823
824 /**
825 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
826 * that creates platform threads.
827 *
828 * @apiNote The following are examples using the builder:
829 * {@snippet :
830 * // Start a daemon thread to run a task
831 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
832 *
833 * // Create an unstarted thread with name "duke", its start() method
834 * // must be invoked to schedule it to execute.
835 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
836 *
837 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
838 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
839 * }
840 *
841 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
842 * @since 21
843 */
1419 public Thread(ThreadGroup group, Runnable task, String name,
1420 long stackSize, boolean inheritInheritableThreadLocals) {
1421 this(group, checkName(name),
1422 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1423 task, stackSize);
1424 }
1425
1426 /**
1427 * Creates a virtual thread to execute a task and schedules it to execute.
1428 *
1429 * <p> This method is equivalent to:
1430 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1431 *
1432 * @param task the object to run when the thread executes
1433 * @return a new, and started, virtual thread
1434 * @see <a href="#inheritance">Inheritance when creating threads</a>
1435 * @since 21
1436 */
1437 public static Thread startVirtualThread(Runnable task) {
1438 Objects.requireNonNull(task);
1439 var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1440 thread.start();
1441 return thread;
1442 }
1443
1444 /**
1445 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1446 * is scheduled by the Java virtual machine rather than the operating system.
1447 *
1448 * @return {@code true} if this thread is a virtual thread
1449 *
1450 * @since 21
1451 */
1452 public final boolean isVirtual() {
1453 return (this instanceof BaseVirtualThread);
1454 }
1455
1456 /**
1457 * Schedules this thread to begin execution. The thread will execute
1458 * independently of the current thread.
1459 *
|
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.misc.TerminatingThreadLocal;
42 import jdk.internal.misc.Unsafe;
43 import jdk.internal.misc.VM;
44 import jdk.internal.vm.Continuation;
45 import jdk.internal.vm.ScopedValueContainer;
46 import jdk.internal.vm.StackableScope;
47 import jdk.internal.vm.ThreadContainer;
48 import jdk.internal.vm.annotation.ForceInline;
49 import jdk.internal.vm.annotation.Hidden;
50 import jdk.internal.vm.annotation.IntrinsicCandidate;
51 import jdk.internal.vm.annotation.Stable;
52 import sun.nio.ch.Interruptible;
53 import static java.util.concurrent.TimeUnit.MILLISECONDS;
54 import static java.util.concurrent.TimeUnit.NANOSECONDS;
55
56 /**
57 * A <i>thread</i> is a thread of execution in a program. The Java
58 * virtual machine allows an application to have multiple threads of
723 static {
724 U = Unsafe.getUnsafe();
725 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
726 }
727 static long next() {
728 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
729 }
730 }
731
732 /**
733 * Initializes a platform Thread.
734 *
735 * @param g the Thread group, can be null
736 * @param name the name of the new Thread
737 * @param characteristics thread characteristics
738 * @param task the object whose run() method gets called
739 * @param stackSize the desired stack size for the new thread, or
740 * zero to indicate that this parameter is to be ignored.
741 */
742 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
743 Thread parent = currentThread();
744 boolean attached = (parent == this); // primordial or JNI attached
745
746 if (attached) {
747 if (g == null) {
748 throw new InternalError("group cannot be null when attaching");
749 }
750 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
751 } else {
752 if (g == null) {
753 // default to current thread's group
754 g = parent.getThreadGroup();
755 }
756 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
757 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
758 }
759
760 if (attached && VM.initLevel() < 1) {
761 this.tid = PRIMORDIAL_TID; // primordial thread
762 } else {
806 }
807 this.contextClassLoader = parent.getContextClassLoader();
808 } else {
809 // default CCL to the system class loader when not inheriting
810 this.contextClassLoader = ClassLoader.getSystemClassLoader();
811 }
812
813 // special value to indicate this is a newly-created Thread
814 this.scopedValueBindings = NEW_THREAD_BINDINGS;
815
816 // create a FieldHolder object, needed when bound to an OS thread
817 if (bound) {
818 ThreadGroup g = Constants.VTHREAD_GROUP;
819 int pri = NORM_PRIORITY;
820 this.holder = new FieldHolder(g, null, -1, pri, true);
821 } else {
822 this.holder = null;
823 }
824 }
825
826 /**
827 * The task that a {@linkplain VirtualThreadScheduler virtual thread scheduler}
828 * executes on a platform thread to
829 * {@linkplain VirtualThreadScheduler#onStart(VirtualThreadTask) start}
830 * or {@linkplain VirtualThreadScheduler#onContinue(VirtualThreadTask) continue}
831 * execution of a virtual thread. While executing the task, the platform thread is
832 * the virtual thread's <em>carrier</em>.
833 *
834 * <p> There is a {@code VirtualThreadTask} object for each virtual thread. The
835 * scheduler arranges to execute its {@link #run()} method when called to start or
836 * continue the virtual thread, if possible on the {@linkplain #preferredCarrier()
837 * preferred carrier thread}. The scheduler may attach an object to the task.
838 *
839 * @since 99
840 */
841 public sealed interface VirtualThreadTask extends Runnable permits
842 VirtualThread.VThreadRunner {
843
844 /**
845 * {@return the virtual thread that this task starts or continues}
846 */
847 Thread thread();
848
849 /**
850 * Runs the task on the current thread as the carrier thread.
851 *
852 * <p> Invoking this method with the interrupted status set will first
853 * clear the interrupt status. Interrupting the carrier thread while
854 * running the task leads to unspecified behavior.
855 *
856 * @throws IllegalStateException if the virtual thread is not in a state to
857 * run on the current thread
858 * @throws IllegalCallerException if the current thread is a virtual thread
859 */
860 @Override
861 void run();
862
863 /**
864 * Returns the preferred carrier thread to execute this task. The scheduler may
865 * choose to ignore this preference.
866 * @return the preferred carrier thread or {@code null} if there is no preferred
867 * carrier thread
868 */
869 Thread preferredCarrier();
870
871 /**
872 * Attaches the given object to this task.
873 * @param att the object to attach
874 * @return the previously-attached object, if any, otherwise {@code null}
875 */
876 Object attach(Object att);
877
878 /**
879 * Retrieves the current attachment.
880 * @return the object currently attached to this task or {@code null} if
881 * there is no attachment
882 */
883 Object attachment();
884 }
885
886 /**
887 * Virtual thread scheduler.
888 *
889 * @apiNote The following example creates a virtual thread scheduler that uses a small
890 * set of platform threads.
891 * {@snippet lang=java :
892 * ExecutorService threadPool = Executors.newFixedThreadPool(4);
893 * var scheduler = new VirtualThreadScheduler() {
894 * private void submit(VirtualThreadTask task) {
895 * Thread caller = Thread.currentThread();
896 * threadPool.submit(() -> {
897 * Thread vthread = task.thread();
898 * Thread carrier = Thread.currentThread();
899 * try {
900 * task.run();
901 * } finally {
902 * assert Thread.currentThread() == carrier;
903 * boolean terminated = !vthread.isAlive();
904 * }
905 * });
906 * }
907 * @Override
908 * public void onStart(VirtualThreadTask task) {
909 * submit(task);
910 * }
911 * @Override
912 * public void onContinue(VirtualThreadTask task) {
913 * submit(task);
914 * }
915 * };
916 * }
917 *
918 * <p> Unless otherwise specified, passing a null argument to a method in
919 * this interface causes a {@code NullPointerException} to be thrown.
920 *
921 * @since 99
922 */
923 public interface VirtualThreadScheduler {
924 /**
925 * Invoked by {@link Thread#start()} to start execution of a {@linkplain
926 * VirtualThreadTask#thread() virtual thread}.
927 * The scheduler's implementation of this method must arrange to execute the
928 * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
929 *
930 * @implNote If invoked from a virtual thread, then the caller virtual thread is
931 * <em>pinned</em> to its carrier while executing the {@code onStart} method.
932 *
933 * @param task the task to execute
934 * @throws RejectedExecutionException if the scheduler cannot accept the task
935 */
936 void onStart(VirtualThreadTask task);
937
938 /**
939 * Invoked to continue execution of a {@linkplain VirtualThreadTask#thread()
940 * virtual thread}.
941 * The scheduler's implementation of this method must arrange to execute the
942 * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
943 *
944 * @implNote If invoked from a virtual thread, then the caller virtual thread is
945 * <em>pinned</em> to its carrier while executing the {@code onContinue} method.
946 *
947 * @param task the task to execute
948 * @throws RejectedExecutionException if the scheduler cannot accept the task
949 */
950 void onContinue(VirtualThreadTask task);
951
952 /**
953 * Creates a new virtual thread, returning the {@code VirtualThreadTask} that the
954 * virtual thread scheduler arranges to execute on a platform thread to start or
955 * continue execution of the virtual thread.
956 *
957 * <p> This method creates a new unstarted {@code Thread} from the current state
958 * of the given builder to run the given task. The {@link VirtualThreadTask#thread()
959 * thread()} method returns the virtual threa. The thread's {@link Thread#start()
960 * start()} method must be invoked to schedule the thread to begin execution.
961 *
962 * @apiNote This method is intended for frameworks that make use of a custom
963 * {@link VirtualThreadScheduler VirtualThreadScheduler} and wish to specify a
964 * preferred carrier thread when creating a virtual thread, or need a reference
965 * to the virtual thread task before the virtual thread is started. The
966 * framework can use the {@link VirtualThreadTask#attach(Object) attach(Object)}
967 * method to attach its context object to the task before the thread is started.
968 *
969 * @implSpec The default implementation creates a new virtual thread. It should
970 * be rare to override this method.
971 *
972 * @param builder the virtual thread builder
973 * @param preferredCarrier the preferred carrirer, can be {@code null}
974 * @param task the object to run when the thread executes
975 * @return the {@code VirtualThreadTask} that scheduler executes
976 * @throws UnsupportedOperationException if this is the built-in default scheduler
977 *
978 * @see <a href="Thread.html#inheritance">Inheritance when creating threads</a>
979 */
980 default VirtualThreadTask newThread(Builder.OfVirtual builder,
981 Thread preferredCarrier,
982 Runnable task) {
983 Objects.requireNonNull(builder);
984 Objects.requireNonNull(task);
985 if (this == VirtualThread.builtinScheduler(false)) {
986 throw new UnsupportedOperationException();
987 }
988 var vbuilder = (ThreadBuilders.VirtualThreadBuilder) builder;
989 var vthread = (VirtualThread) vbuilder.unstarted(task, preferredCarrier);
990 return vthread.virtualThreadTask();
991 }
992
993 /**
994 * Schedules a task that becomes enabled for execution after the given delay.
995 *
996 * <p> This method is invoked to schedule delayed tasks in support of timed
997 * operations and methods such as {@link Thread#sleep(long)} and {@link
998 * Object#wait(long)}. The scheduler should arrange to execute the task on
999 * a platform thread.
1000 *
1001 * @implSpec The default implementation schedules the task to execute after
1002 * the given delay. The task executes on JDK internal thread. An implementation
1003 * may wish to override this method when it is capable of scheduling delayed
1004 * tasks.
1005 *
1006 * @param task the task to execute
1007 * @param delay the time from now to delay execution
1008 * @param unit the time unit of the delay parameter
1009 * @return a Future representing pending completion of the task
1010 */
1011 default Future<?> schedule(Runnable task, long delay, TimeUnit unit) {
1012 return VirtualThread.DelayedTaskSchedulers.schedule(task, delay, unit);
1013 }
1014 }
1015
1016 /**
1017 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
1018 * that creates platform threads.
1019 *
1020 * @apiNote The following are examples using the builder:
1021 * {@snippet :
1022 * // Start a daemon thread to run a task
1023 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
1024 *
1025 * // Create an unstarted thread with name "duke", its start() method
1026 * // must be invoked to schedule it to execute.
1027 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
1028 *
1029 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
1030 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
1031 * }
1032 *
1033 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
1034 * @since 21
1035 */
1611 public Thread(ThreadGroup group, Runnable task, String name,
1612 long stackSize, boolean inheritInheritableThreadLocals) {
1613 this(group, checkName(name),
1614 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1615 task, stackSize);
1616 }
1617
1618 /**
1619 * Creates a virtual thread to execute a task and schedules it to execute.
1620 *
1621 * <p> This method is equivalent to:
1622 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1623 *
1624 * @param task the object to run when the thread executes
1625 * @return a new, and started, virtual thread
1626 * @see <a href="#inheritance">Inheritance when creating threads</a>
1627 * @since 21
1628 */
1629 public static Thread startVirtualThread(Runnable task) {
1630 Objects.requireNonNull(task);
1631 var thread = ThreadBuilders.newVirtualThread(null, 0, task);
1632 thread.start();
1633 return thread;
1634 }
1635
1636 /**
1637 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1638 * is scheduled by the Java virtual machine rather than the operating system.
1639 *
1640 * @return {@code true} if this thread is a virtual thread
1641 *
1642 * @since 21
1643 */
1644 public final boolean isVirtual() {
1645 return (this instanceof BaseVirtualThread);
1646 }
1647
1648 /**
1649 * Schedules this thread to begin execution. The thread will execute
1650 * independently of the current thread.
1651 *
|