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.foreign.ConfinedSegmentPool;
38 import jdk.internal.event.ThreadSleepEvent;
39 import jdk.internal.misc.TerminatingThreadLocal;
40 import jdk.internal.misc.Unsafe;
41 import jdk.internal.misc.VM;
42 import jdk.internal.vm.Continuation;
43 import jdk.internal.vm.ScopedValueContainer;
44 import jdk.internal.vm.StackableScope;
45 import jdk.internal.vm.ThreadContainer;
46 import jdk.internal.vm.annotation.ForceInline;
47 import jdk.internal.vm.annotation.Hidden;
48 import jdk.internal.vm.annotation.IntrinsicCandidate;
49 import jdk.internal.vm.annotation.Stable;
50 import sun.nio.ch.Interruptible;
51 import static java.util.concurrent.TimeUnit.MILLISECONDS;
52 import static java.util.concurrent.TimeUnit.NANOSECONDS;
53
54 /**
55 * A <i>thread</i> is a thread of execution in a program. The Java
745 static {
746 U = Unsafe.getUnsafe();
747 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
748 }
749 static long next() {
750 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
751 }
752 }
753
754 /**
755 * Initializes a platform Thread.
756 *
757 * @param g the Thread group, can be null
758 * @param name the name of the new Thread
759 * @param characteristics thread characteristics
760 * @param task the object whose run() method gets called
761 * @param stackSize the desired stack size for the new thread, or
762 * zero to indicate that this parameter is to be ignored.
763 */
764 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
765
766 Thread parent = currentThread();
767 boolean attached = (parent == this); // primordial or JNI attached
768
769 if (attached) {
770 if (g == null) {
771 throw new InternalError("group cannot be null when attaching");
772 }
773 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
774 } else {
775 if (g == null) {
776 // default to current thread's group
777 g = parent.getThreadGroup();
778 }
779 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
780 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
781 }
782
783 if (attached && VM.initLevel() < 1) {
784 this.tid = PRIMORDIAL_TID; // primordial thread
785 } else {
829 }
830 this.contextClassLoader = parent.getContextClassLoader();
831 } else {
832 // default CCL to the system class loader when not inheriting
833 this.contextClassLoader = ClassLoader.getSystemClassLoader();
834 }
835
836 // special value to indicate this is a newly-created Thread
837 this.scopedValueBindings = NEW_THREAD_BINDINGS;
838
839 // create a FieldHolder object, needed when bound to an OS thread
840 if (bound) {
841 ThreadGroup g = Constants.VTHREAD_GROUP;
842 int pri = NORM_PRIORITY;
843 this.holder = new FieldHolder(g, null, -1, pri, true);
844 } else {
845 this.holder = null;
846 }
847 }
848
849 /**
850 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
851 * that creates platform threads.
852 *
853 * @apiNote The following are examples using the builder:
854 * {@snippet :
855 * // Start a daemon thread to run a task
856 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
857 *
858 * // Create an unstarted thread with name "duke", its start() method
859 * // must be invoked to schedule it to execute.
860 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
861 *
862 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
863 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
864 * }
865 *
866 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
867 * @since 21
868 */
1444 public Thread(ThreadGroup group, Runnable task, String name,
1445 long stackSize, boolean inheritInheritableThreadLocals) {
1446 this(group, checkName(name),
1447 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1448 task, stackSize);
1449 }
1450
1451 /**
1452 * Creates a virtual thread to execute a task and schedules it to execute.
1453 *
1454 * <p> This method is equivalent to:
1455 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1456 *
1457 * @param task the object to run when the thread executes
1458 * @return a new, and started, virtual thread
1459 * @see <a href="#inheritance">Inheritance when creating threads</a>
1460 * @since 21
1461 */
1462 public static Thread startVirtualThread(Runnable task) {
1463 Objects.requireNonNull(task);
1464 var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
1465 thread.start();
1466 return thread;
1467 }
1468
1469 /**
1470 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1471 * is scheduled by the Java virtual machine rather than the operating system.
1472 *
1473 * @return {@code true} if this thread is a virtual thread
1474 *
1475 * @since 21
1476 */
1477 public final boolean isVirtual() {
1478 return (this instanceof BaseVirtualThread);
1479 }
1480
1481 /**
1482 * Schedules this thread to begin execution. The thread will execute
1483 * independently of the current thread.
1484 *
|
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.foreign.ConfinedSegmentPool;
41 import jdk.internal.event.ThreadSleepEvent;
42 import jdk.internal.misc.TerminatingThreadLocal;
43 import jdk.internal.misc.Unsafe;
44 import jdk.internal.misc.VM;
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 static java.util.concurrent.TimeUnit.MILLISECONDS;
55 import static java.util.concurrent.TimeUnit.NANOSECONDS;
56
57 /**
58 * A <i>thread</i> is a thread of execution in a program. The Java
748 static {
749 U = Unsafe.getUnsafe();
750 NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
751 }
752 static long next() {
753 return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
754 }
755 }
756
757 /**
758 * Initializes a platform Thread.
759 *
760 * @param g the Thread group, can be null
761 * @param name the name of the new Thread
762 * @param characteristics thread characteristics
763 * @param task the object whose run() method gets called
764 * @param stackSize the desired stack size for the new thread, or
765 * zero to indicate that this parameter is to be ignored.
766 */
767 Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
768 Thread parent = currentThread();
769 boolean attached = (parent == this); // primordial or JNI attached
770
771 if (attached) {
772 if (g == null) {
773 throw new InternalError("group cannot be null when attaching");
774 }
775 this.holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false);
776 } else {
777 if (g == null) {
778 // default to current thread's group
779 g = parent.getThreadGroup();
780 }
781 int priority = Math.min(parent.getPriority(), g.getMaxPriority());
782 this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
783 }
784
785 if (attached && VM.initLevel() < 1) {
786 this.tid = PRIMORDIAL_TID; // primordial thread
787 } else {
831 }
832 this.contextClassLoader = parent.getContextClassLoader();
833 } else {
834 // default CCL to the system class loader when not inheriting
835 this.contextClassLoader = ClassLoader.getSystemClassLoader();
836 }
837
838 // special value to indicate this is a newly-created Thread
839 this.scopedValueBindings = NEW_THREAD_BINDINGS;
840
841 // create a FieldHolder object, needed when bound to an OS thread
842 if (bound) {
843 ThreadGroup g = Constants.VTHREAD_GROUP;
844 int pri = NORM_PRIORITY;
845 this.holder = new FieldHolder(g, null, -1, pri, true);
846 } else {
847 this.holder = null;
848 }
849 }
850
851 /**
852 * The task that a {@linkplain VirtualThreadScheduler virtual thread scheduler}
853 * executes on a platform thread to
854 * {@linkplain VirtualThreadScheduler#onStart(VirtualThreadTask) start}
855 * or {@linkplain VirtualThreadScheduler#onContinue(VirtualThreadTask) continue}
856 * execution of a virtual thread. While executing the task, the platform thread is
857 * the virtual thread's <em>carrier</em>.
858 *
859 * <p> There is a {@code VirtualThreadTask} object for each virtual thread. The
860 * scheduler arranges to execute its {@link #run()} method when called to start or
861 * continue the virtual thread, if possible on the {@linkplain #preferredCarrier()
862 * preferred carrier thread}. The scheduler may attach an object to the task.
863 *
864 * @since 99
865 */
866 public sealed interface VirtualThreadTask extends Runnable permits VirtualThread.VThreadTask {
867
868 /**
869 * {@return the virtual thread that this task starts or continues}
870 */
871 Thread thread();
872
873 /**
874 * Runs the task on the current thread as the carrier thread.
875 *
876 * <p> Invoking this method with the interrupted status set will first
877 * clear the interrupt status. Interrupting the carrier thread while
878 * running the task leads to unspecified behavior.
879 *
880 * @throws IllegalStateException if the virtual thread is not in a state to
881 * run on the current thread
882 * @throws IllegalCallerException if the current thread is a virtual thread
883 */
884 @Override
885 void run();
886
887 /**
888 * Returns the preferred carrier thread to execute this task. The scheduler may
889 * choose to ignore this preference.
890 * @return the preferred carrier thread or {@code null} if there is no preferred
891 * carrier thread
892 */
893 Thread preferredCarrier();
894
895 /**
896 * Attaches the given object to this task.
897 * @param att the object to attach
898 * @return the previously-attached object, if any, otherwise {@code null}
899 */
900 Object attach(Object att);
901
902 /**
903 * Retrieves the current attachment.
904 * @return the object currently attached to this task or {@code null} if
905 * there is no attachment
906 */
907 Object attachment();
908 }
909
910 /**
911 * Virtual thread scheduler.
912 *
913 * @apiNote The following example creates a virtual thread scheduler that uses a small
914 * set of platform threads.
915 * {@snippet lang=java :
916 * ExecutorService threadPool = Executors.newFixedThreadPool(4);
917 * var scheduler = new VirtualThreadScheduler() {
918 * private void submit(VirtualThreadTask task) {
919 * Thread caller = Thread.currentThread();
920 * threadPool.submit(() -> {
921 * Thread vthread = task.thread();
922 * Thread carrier = Thread.currentThread();
923 * try {
924 * task.run();
925 * } finally {
926 * assert Thread.currentThread() == carrier;
927 * boolean terminated = !vthread.isAlive();
928 * }
929 * });
930 * }
931 * @Override
932 * public void onStart(VirtualThreadTask task) {
933 * submit(task);
934 * }
935 * @Override
936 * public void onContinue(VirtualThreadTask task) {
937 * submit(task);
938 * }
939 * };
940 * }
941 *
942 * <p> Unless otherwise specified, passing a null argument to a method in
943 * this interface causes a {@code NullPointerException} to be thrown.
944 *
945 * @since 99
946 */
947 public interface VirtualThreadScheduler {
948 /**
949 * Invoked by {@link Thread#start()} to start execution of a {@linkplain
950 * VirtualThreadTask#thread() virtual thread}.
951 * The scheduler's implementation of this method must arrange to execute the
952 * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
953 *
954 * @implNote If invoked from a virtual thread, then the caller virtual thread is
955 * <em>pinned</em> to its carrier while executing the {@code onStart} method.
956 *
957 * @param task the task to execute
958 * @throws RejectedExecutionException if the scheduler cannot accept the task
959 */
960 void onStart(VirtualThreadTask task);
961
962 /**
963 * Invoked to continue execution of a {@linkplain VirtualThreadTask#thread()
964 * virtual thread}.
965 * The scheduler's implementation of this method must arrange to execute the
966 * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
967 *
968 * @implNote If invoked from a virtual thread, then the caller virtual thread is
969 * <em>pinned</em> to its carrier while executing the {@code onContinue} method.
970 *
971 * @param task the task to execute
972 * @throws RejectedExecutionException if the scheduler cannot accept the task
973 */
974 void onContinue(VirtualThreadTask task);
975
976 /**
977 * Creates a new virtual thread, returning the {@code VirtualThreadTask} that the
978 * virtual thread scheduler arranges to execute on a platform thread to start or
979 * continue execution of the virtual thread.
980 *
981 * <p> This method creates a new unstarted {@code Thread} from the current state
982 * of the given builder to run the given task. The {@link VirtualThreadTask#thread()
983 * thread()} method returns the virtual threa. The thread's {@link Thread#start()
984 * start()} method must be invoked to schedule the thread to begin execution.
985 *
986 * @apiNote This method is intended for frameworks that make use of a custom
987 * {@link VirtualThreadScheduler VirtualThreadScheduler} and wish to specify a
988 * preferred carrier thread when creating a virtual thread, or need a reference
989 * to the virtual thread task before the virtual thread is started. The
990 * framework can use the {@link VirtualThreadTask#attach(Object) attach(Object)}
991 * method to attach its context object to the task before the thread is started.
992 *
993 * @implSpec The default implementation creates a new virtual thread. It should
994 * be rare to override this method.
995 *
996 * @param builder the virtual thread builder
997 * @param preferredCarrier the preferred carrirer, can be {@code null}
998 * @param task the object to run when the thread executes
999 * @return the {@code VirtualThreadTask} that scheduler executes
1000 * @throws UnsupportedOperationException if this is the built-in default scheduler
1001 *
1002 * @see <a href="Thread.html#inheritance">Inheritance when creating threads</a>
1003 */
1004 default VirtualThreadTask newThread(Builder.OfVirtual builder,
1005 Thread preferredCarrier,
1006 Runnable task) {
1007 Objects.requireNonNull(builder);
1008 Objects.requireNonNull(task);
1009 if (this == VirtualThread.builtinScheduler(false)) {
1010 throw new UnsupportedOperationException();
1011 }
1012 var vbuilder = (ThreadBuilders.VirtualThreadBuilder) builder;
1013 var vthread = (VirtualThread) vbuilder.unstarted(task, preferredCarrier);
1014 return vthread.virtualThreadTask();
1015 }
1016
1017 /**
1018 * Schedules a task that becomes enabled for execution after the given delay.
1019 *
1020 * <p> This method is invoked to schedule delayed tasks in support of timed
1021 * operations and methods such as {@link Thread#sleep(long)} and {@link
1022 * Object#wait(long)}. The scheduler should arrange to execute the task on
1023 * a platform thread.
1024 *
1025 * @implSpec The default implementation schedules the task to execute after
1026 * the given delay. The task executes on JDK internal thread. An implementation
1027 * may wish to override this method when it is capable of scheduling delayed
1028 * tasks.
1029 *
1030 * @param task the task to execute
1031 * @param delay the time from now to delay execution
1032 * @param unit the time unit of the delay parameter
1033 * @return a Future representing pending completion of the task
1034 */
1035 default Future<?> schedule(Runnable task, long delay, TimeUnit unit) {
1036 return VirtualThread.DelayedTaskSchedulers.schedule(task, delay, unit);
1037 }
1038 }
1039
1040 /**
1041 * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
1042 * that creates platform threads.
1043 *
1044 * @apiNote The following are examples using the builder:
1045 * {@snippet :
1046 * // Start a daemon thread to run a task
1047 * Thread thread = Thread.ofPlatform().daemon().start(runnable);
1048 *
1049 * // Create an unstarted thread with name "duke", its start() method
1050 * // must be invoked to schedule it to execute.
1051 * Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);
1052 *
1053 * // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
1054 * ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();
1055 * }
1056 *
1057 * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects.
1058 * @since 21
1059 */
1635 public Thread(ThreadGroup group, Runnable task, String name,
1636 long stackSize, boolean inheritInheritableThreadLocals) {
1637 this(group, checkName(name),
1638 (inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
1639 task, stackSize);
1640 }
1641
1642 /**
1643 * Creates a virtual thread to execute a task and schedules it to execute.
1644 *
1645 * <p> This method is equivalent to:
1646 * <pre>{@code Thread.ofVirtual().start(task); }</pre>
1647 *
1648 * @param task the object to run when the thread executes
1649 * @return a new, and started, virtual thread
1650 * @see <a href="#inheritance">Inheritance when creating threads</a>
1651 * @since 21
1652 */
1653 public static Thread startVirtualThread(Runnable task) {
1654 Objects.requireNonNull(task);
1655 var thread = ThreadBuilders.newVirtualThread(null, 0, task);
1656 thread.start();
1657 return thread;
1658 }
1659
1660 /**
1661 * Returns {@code true} if this thread is a virtual thread. A virtual thread
1662 * is scheduled by the Java virtual machine rather than the operating system.
1663 *
1664 * @return {@code true} if this thread is a virtual thread
1665 *
1666 * @since 21
1667 */
1668 public final boolean isVirtual() {
1669 return (this instanceof BaseVirtualThread);
1670 }
1671
1672 /**
1673 * Schedules this thread to begin execution. The thread will execute
1674 * independently of the current thread.
1675 *
|