< prev index next >

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

Print this page
*** 29,26 ***
--- 29,32 ---
  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.Executor;
+ import java.util.concurrent.RejectedExecutionException;
  import java.util.concurrent.ThreadFactory;
  import java.util.concurrent.StructureViolationException;
  import java.util.concurrent.locks.LockSupport;
  import jdk.internal.event.ThreadSleepEvent;
+ import jdk.internal.javac.Restricted;
  import jdk.internal.misc.TerminatingThreadLocal;
  import jdk.internal.misc.Unsafe;
  import jdk.internal.misc.VM;
+ import jdk.internal.reflect.CallerSensitive;
+ import jdk.internal.reflect.Reflection;
  import jdk.internal.vm.Continuation;
  import jdk.internal.vm.ScopedValueContainer;
  import jdk.internal.vm.StackableScope;
  import jdk.internal.vm.ThreadContainer;
  import jdk.internal.vm.annotation.ForceInline;
  import jdk.internal.vm.annotation.Hidden;
  import jdk.internal.vm.annotation.IntrinsicCandidate;
  import jdk.internal.vm.annotation.Stable;
  import sun.nio.ch.Interruptible;
+ 
  import static java.util.concurrent.TimeUnit.MILLISECONDS;
  import static java.util.concurrent.TimeUnit.NANOSECONDS;
  
  /**
   * A <i>thread</i> is a thread of execution in a program. The Java

*** 212,12 ***
   * <h2>Null Handling</h2>
   * Unless otherwise specified, passing a {@code null} argument to a constructor
   * or method in this class will cause a {@link NullPointerException} to be thrown.
   *
   * @implNote
!  * In the JDK Reference Implementation, the virtual thread scheduler may be configured
!  * with the following system properties:
   * <table class="striped">
   * <caption style="display:none">System properties</caption>
   *   <thead>
   *   <tr>
   *     <th scope="col">System property</th>
--- 218,12 ---
   * <h2>Null Handling</h2>
   * Unless otherwise specified, passing a {@code null} argument to a constructor
   * or method in this class will cause a {@link NullPointerException} to be thrown.
   *
   * @implNote
!  * In the JDK Reference Implementation, the following system properties may be used to
!  * configure the built-in default virtual thread scheduler:
   * <table class="striped">
   * <caption style="display:none">System properties</caption>
   *   <thead>
   *   <tr>
   *     <th scope="col">System property</th>

*** 235,11 ***
   *   </tr>
   *   <tr>
   *     <th scope="row">
   *       {@systemProperty jdk.virtualThreadScheduler.maxPoolSize}
   *     </th>
!  *     <td> The maximum number of platform threads available to the scheduler.
   *       It defaults to 256. </td>
   *   </tr>
   *   </tbody>
   * </table>
   * <p> The virtual thread scheduler can be monitored and managed with the
--- 241,11 ---
   *   </tr>
   *   <tr>
   *     <th scope="row">
   *       {@systemProperty jdk.virtualThreadScheduler.maxPoolSize}
   *     </th>
!  *     <td> The maximum number of platform threads available to the default scheduler.
   *       It defaults to 256. </td>
   *   </tr>
   *   </tbody>
   * </table>
   * <p> The virtual thread scheduler can be monitored and managed with the

*** 284,10 ***
--- 290,13 ---
          final long stackSize;
          volatile int priority;
          volatile boolean daemon;
          volatile int threadStatus;
  
+         // Used by NativeThread for signalling, set lazily, read from any thread
+         @Stable long nativeThreadID;
+ 
          // This map is maintained by the ThreadLocal class
          ThreadLocal.ThreadLocalMap terminatingThreadLocals;
  
          FieldHolder(ThreadGroup group,
                      Runnable task,

*** 310,10 ***
--- 319,18 ---
  
      void setTerminatingThreadLocals(ThreadLocal.ThreadLocalMap map) {
          holder.terminatingThreadLocals = map;
      }
  
+     long nativeThreadID() {
+         return holder.nativeThreadID;
+     }
+ 
+     void setNativeThreadID(long id) {
+         holder.nativeThreadID = id;
+     }
+ 
      /*
       * ThreadLocal values pertaining to this thread. This map is maintained
       * by the ThreadLocal class.
       */
      private ThreadLocal.ThreadLocalMap threadLocals;

*** 724,11 ***
       * @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) {
--- 741,10 ---

*** 808,10 ***
--- 824,169 ---
          } 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. A scheduler may attach an object to the task.
+      *
+      * @since 99
+      */
+     public sealed interface VirtualThreadTask extends Runnable permits
+             VirtualThread.BuiltinSchedulerTask, VirtualThread.CustomSchedulerTask {
+ 
+         /**
+          * {@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();
+ 
+         /**
+          * 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.
+      *
+      * @see Builder.OfVirtual#scheduler(VirtualThreadScheduler)
+      * @since 99
+      * @see VirtualThreadScheduler
+      */
+     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);
+ 
+         /**
+          * {@return a virtual thread scheduler that delegates tasks to the given executor}
+          * @param executor the executor
+          */
+         static VirtualThreadScheduler adapt(Executor executor) {
+             Objects.requireNonNull(executor);
+             return new VirtualThreadScheduler() {
+                 @Override
+                 public void onStart(VirtualThreadTask task) {
+                     executor.execute(task);
+                 }
+                 @Override
+                 public void onContinue(VirtualThreadTask task) {
+                     executor.execute(task);
+                 }
+             };
+         }
+ 
+         /**
+          * {@return the virtual thread scheduler for the current virtual thread}
+          * @throws UnsupportedOperationException if the current thread is not a virtual
+          * thread or scheduling virtual threads to a user-provided scheduler is not
+          * supported by this VM
+          */
+         @CallerSensitive
+         @Restricted
+         static VirtualThreadScheduler current() {
+             Class<?> caller = Reflection.getCallerClass();
+             caller.getModule().ensureNativeAccess(VirtualThreadScheduler.class,
+                     "current",
+                     caller,
+                     false);
+             if (Thread.currentThread() instanceof VirtualThread vthread) {
+                 return vthread.scheduler(false);
+             } else {
+                 throw new UnsupportedOperationException();
+             }
+         }
+     }
+ 
      /**
       * Returns a builder for creating a platform {@code Thread} or {@code ThreadFactory}
       * that creates platform threads.
       *
       * @apiNote The following are examples using the builder:

*** 1062,10 ***
--- 1237,36 ---
               */
              @Override OfVirtual name(String prefix, long start);
  
              @Override OfVirtual inheritInheritableThreadLocals(boolean inherit);
              @Override OfVirtual uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
+ 
+             /**
+              * Sets the scheduler.
+              *
+              * <p> The virtual thread will be scheduled by the Java virtual machine with
+              * the given scheduler. The scheduler's {@link
+              * VirtualThreadScheduler#onStart(VirtualThreadTask) onStart} and
+              * {@link VirtualThreadScheduler#onContinue(VirtualThreadTask) onContinue}
+              * methods may be invoked in the context of a virtual thread. The scheduler
+              * must arrange to execute the {@link VirtualThreadTask}'s
+              * {@code run} method on a platform thread. Attempting to execute the run
+              * method in a virtual thread causes {@link WrongThreadException} to be thrown.
+              * The {@code onStart} and {@code onContinue }methods may be invoked at
+              * sensitive times (e.g. when unparking a thread) so care should be taken to
+              * not directly execute the task on the <em>current thread</em>.
+              *
+              * @param scheduler the scheduler
+              * @return this builder
+              * @throws UnsupportedOperationException if scheduling virtual threads to a
+              *         user-provided scheduler is not supported by this VM
+              *
+              * @since 99
+              */
+             @CallerSensitive
+             @Restricted
+             OfVirtual scheduler(VirtualThreadScheduler scheduler);
          }
      }
  
      /**
       * Throws CloneNotSupportedException as a Thread can not be meaningfully

*** 1412,10 ***
--- 1613,11 ---
                  task, stackSize);
      }
  
      /**
       * Creates a virtual thread to execute a task and schedules it to execute.
+      * The thread is scheduled by the default virtual thread scheduler.
       *
       * <p> This method is equivalent to:
       * <pre>{@code Thread.ofVirtual().start(task); }</pre>
       *
       * @param task the object to run when the thread executes
< prev index next >