< prev index next >

src/java.base/share/classes/java/lang/Thread.java

Print this page
@@ -29,12 +29,15 @@
  import java.lang.reflect.Field;
  import java.time.Duration;
  import java.util.Map;
  import java.util.HashMap;
  import java.util.Objects;
- import java.util.concurrent.ThreadFactory;
+ import java.util.concurrent.Future;
+ import java.util.concurrent.RejectedExecutionException;
  import java.util.concurrent.StructureViolationException;
+ import java.util.concurrent.ThreadFactory;
+ import java.util.concurrent.TimeUnit;
  import java.util.concurrent.locks.LockSupport;
  import jdk.internal.event.ThreadSleepEvent;
  import jdk.internal.misc.TerminatingThreadLocal;
  import jdk.internal.misc.Unsafe;
  import jdk.internal.misc.VM;

@@ -735,11 +738,10 @@
       * @param task the object whose run() method gets called
       * @param stackSize the desired stack size for the new thread, or
       *        zero to indicate that this parameter is to be ignored.
       */
      Thread(ThreadGroup g, String name, int characteristics, Runnable task, long stackSize) {
- 
          Thread parent = currentThread();
          boolean attached = (parent == this);   // primordial or JNI attached
  
          if (attached) {
              if (g == null) {

@@ -819,10 +821,200 @@
          } else {
              this.holder = null;
          }
      }
  
+     /**
+      * The task that a {@linkplain VirtualThreadScheduler virtual thread scheduler}
+      * executes on a platform thread to
+      * {@linkplain VirtualThreadScheduler#onStart(VirtualThreadTask) start}
+      * or {@linkplain VirtualThreadScheduler#onContinue(VirtualThreadTask) continue}
+      * execution of a virtual thread. While executing the task, the platform thread is
+      * the virtual thread's <em>carrier</em>.
+      *
+      * <p> There is a {@code VirtualThreadTask} object for each virtual thread. The
+      * scheduler arranges to execute its {@link #run()} method when called to start or
+      * continue the virtual thread, if possible on the {@linkplain #preferredCarrier()
+      * preferred carrier thread}. The scheduler may attach an object to the task.
+      *
+      * @since 99
+      */
+     public sealed interface VirtualThreadTask extends Runnable permits
+             VirtualThread.VThreadRunner {
+ 
+         /**
+          * {@return the virtual thread that this task starts or continues}
+          */
+         Thread thread();
+ 
+         /**
+          * Runs the task on the current thread as the carrier thread.
+          *
+          * <p> Invoking this method with the interrupted status set will first
+          * clear the interrupt status. Interrupting the carrier thread while
+          * running the task leads to unspecified behavior.
+          *
+          * @throws IllegalStateException if the virtual thread is not in a state to
+          * run on the current thread
+          * @throws IllegalCallerException if the current thread is a virtual thread
+          */
+         @Override
+         void run();
+ 
+         /**
+          * Returns the preferred carrier thread to execute this task. The scheduler may
+          * choose to ignore this preference.
+          * @return the preferred carrier thread or {@code null} if there is no preferred
+          * carrier thread
+          */
+         Thread preferredCarrier();
+ 
+         /**
+          * Attaches the given object to this task.
+          * @param att the object to attach
+          * @return the previously-attached object, if any, otherwise {@code null}
+          */
+         Object attach(Object att);
+ 
+         /**
+          * Retrieves the current attachment.
+          * @return the object currently attached to this task or {@code null} if
+          * there is no attachment
+          */
+         Object attachment();
+     }
+ 
+     /**
+      * Virtual thread scheduler.
+      *
+      * @apiNote The following example creates a virtual thread scheduler that uses a small
+      * set of platform threads.
+      * {@snippet lang=java :
+      *     ExecutorService threadPool = Executors.newFixedThreadPool(4);
+      *     var scheduler = new VirtualThreadScheduler() {
+      *         private void submit(VirtualThreadTask task) {
+      *             Thread caller = Thread.currentThread();
+      *             threadPool.submit(() -> {
+      *                 Thread vthread = task.thread();
+      *                 Thread carrier = Thread.currentThread();
+      *                 try {
+      *                     task.run();
+      *                 } finally {
+      *                     assert Thread.currentThread() == carrier;
+      *                     boolean terminated = !vthread.isAlive();
+      *                 }
+      *             });
+      *         }
+      *         @Override
+      *         public void onStart(VirtualThreadTask task) {
+      *             submit(task);
+      *         }
+      *         @Override
+      *         public void onContinue(VirtualThreadTask task) {
+      *             submit(task);
+      *         }
+      *    };
+      * }
+      *
+      * <p> Unless otherwise specified, passing a null argument to a method in
+      * this interface causes a {@code NullPointerException} to be thrown.
+      *
+      * @since 99
+      */
+     public interface VirtualThreadScheduler {
+         /**
+          * Invoked by {@link Thread#start()} to start execution of a {@linkplain
+          * VirtualThreadTask#thread() virtual thread}.
+          * The scheduler's implementation of this method must arrange to execute the
+          * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
+          *
+          * @implNote If invoked from a virtual thread, then the caller virtual thread is
+          * <em>pinned</em> to its carrier while executing the {@code onStart} method.
+          *
+          * @param task the task to execute
+          * @throws RejectedExecutionException if the scheduler cannot accept the task
+          */
+         void onStart(VirtualThreadTask task);
+ 
+         /**
+          * Invoked to continue execution of a {@linkplain VirtualThreadTask#thread()
+          * virtual thread}.
+          * The scheduler's implementation of this method must arrange to execute the
+          * given task's {@link VirtualThreadTask#run() run()} method on a platform thread.
+          *
+          * @implNote If invoked from a virtual thread, then the caller virtual thread is
+          * <em>pinned</em> to its carrier while executing the {@code onContinue} method.
+          *
+          * @param task the task to execute
+          * @throws RejectedExecutionException if the scheduler cannot accept the task
+          */
+         void onContinue(VirtualThreadTask task);
+ 
+         /**
+          * Creates a new virtual thread, returning the {@code VirtualThreadTask} that the
+          * virtual thread scheduler arranges to execute on a platform thread to start or
+          * continue execution of the virtual thread.
+          *
+          * <p> This method creates a new unstarted {@code Thread} from the current state
+          * of the given builder to run the given task. The {@link VirtualThreadTask#thread()
+          * thread()} method returns the virtual threa. The thread's {@link Thread#start()
+          * start()} method must be invoked to schedule the thread to begin execution.
+          *
+          * @apiNote This method is intended for frameworks that make use of a custom
+          * {@link VirtualThreadScheduler VirtualThreadScheduler} and wish to specify a
+          * preferred carrier thread when creating a virtual thread, or need a reference
+          * to the virtual thread task before the virtual thread is started. The
+          * framework can use the {@link VirtualThreadTask#attach(Object) attach(Object)}
+          * method to attach its context object to the task before the thread is started.
+          *
+          * @implSpec The default implementation creates a new virtual thread. It should
+          * be rare to override this method.
+          *
+          * @param builder the virtual thread builder
+          * @param preferredCarrier the preferred carrirer, can be {@code null}
+          * @param task the object to run when the thread executes
+          * @return the {@code VirtualThreadTask} that scheduler executes
+          * @throws UnsupportedOperationException if this is the built-in default scheduler
+          *
+          * @see <a href="Thread.html#inheritance">Inheritance when creating threads</a>
+          */
+         default VirtualThreadTask newThread(Builder.OfVirtual builder,
+                                             Thread preferredCarrier,
+                                             Runnable task) {
+             Objects.requireNonNull(builder);
+             Objects.requireNonNull(task);
+             if (this == VirtualThread.builtinScheduler(false)) {
+                 throw new UnsupportedOperationException();
+             }
+             var vbuilder = (ThreadBuilders.VirtualThreadBuilder) builder;
+             var vthread = (VirtualThread) vbuilder.unstarted(task, preferredCarrier);
+             return vthread.virtualThreadTask();
+         }
+ 
+         /**
+          * Schedules a task that becomes enabled for execution after the given delay.
+          *
+          * <p> This method is invoked to schedule delayed tasks in support of timed
+          * operations and methods such as {@link Thread#sleep(long)} and {@link
+          * Object#wait(long)}. The scheduler should arrange to execute the task on
+          * a platform thread.
+          *
+          * @implSpec The default implementation schedules the task to execute after
+          * the given delay. The task executes on JDK internal thread. An implementation
+          * may wish to override this method when it is capable of scheduling delayed
+          * tasks.
+          *
+          * @param task the task to execute
+          * @param delay the time from now to delay execution
+          * @param unit the time unit of the delay parameter
+          * @return a Future representing pending completion of the task
+          */
+         default Future<?> schedule(Runnable task, long delay, TimeUnit unit) {
+             return VirtualThread.DelayedTaskSchedulers.schedule(task, delay, unit);
+         }
+     }
+ 
      /**
       * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
       * that creates platform threads.
       *
       * @apiNote The following are examples using the builder:

@@ -1434,11 +1626,11 @@
       * @see <a href="#inheritance">Inheritance when creating threads</a>
       * @since 21
       */
      public static Thread startVirtualThread(Runnable task) {
          Objects.requireNonNull(task);
-         var thread = ThreadBuilders.newVirtualThread(null, null, 0, task);
+         var thread = ThreadBuilders.newVirtualThread(null, 0, task);
          thread.start();
          return thread;
      }
  
      /**
< prev index next >