/*
* Copyright ( c ) 1994 , 2022 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation . Oracle designates this
* particular file as subject to the " Classpath " exception as provided
* by Oracle in the LICENSE file that accompanied this code .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*/
package java.lang;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
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.locks.LockSupport;
import java.util.function .Predicate;
import java.util.stream.Stream;
import jdk.internal.event.ThreadSleepEvent;
import jdk.internal.javac.PreviewFeature;
import jdk.internal.misc.PreviewFeatures;
import jdk.internal.misc.StructureViolationExceptions;
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 sun.nio.ch.Interruptible;
import sun.security.util.SecurityConstants;
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
* virtual machine allows an application to have multiple threads of
ecution running concurrently .
*
* < p > { @ code Thread } defines constructors and a { @ link Builder } to create threads .
* { @ linkplain # start ( ) Starting } a thread schedules it to execute its { @ link # run ( ) run }
* method . The newly started thread executes concurrently with the thread that caused
* it to start .
*
* < p > A thread < i > terminates < / i > if either its { @ code run } method completes normally ,
* or if its { @ code run } method completes abruptly and the appropriate { @ linkplain
* Thread . UncaughtExceptionHandler uncaught exception handler } completes normally or
* abruptly . With no code left to run , the thread has completed execution . The
* { @ link # join ( ) join } method can be used to wait for a thread
*
* < p > Threads have a unique { @ linkplain # threadId ( ) identifier } and a { @ linkplain
* # getName ( ) name } . The identifier is generated when a { @ code Thread } is created
* and cannot be changed . The thread name can be specified when creating a thread
* or can be { @ linkplain # setName ( String ) changed } at a later time .
* < p > Threads support { @ link ThreadLocal } variables . These are variables that are
* local to a thread , meaning a thread can have a copy of a variable that is set to
* a value that is independent of the value set by other threads . Thread also supports
* { @ link InheritableThreadLocal } variables that are thread local variables that are
* inherited at Thread creation time from the parent Thread . Thread supports a special
* inheritable thread local for the thread { @ linkplain # getContextClassLoader ( )
* context - class - loader } .
*
* < h2 > < a id = " platform - threads " > Platform threads < / a > < / h2 >
* < p > { @ code Thread } supports the creation of < i > platform threads < / i > that are
* typically mapped 1 : 1 to kernel threads scheduled by the operating system .
* threads usually have a large other resources that
* maintained by the operating system . Platforms threads are suitable for executing
* all types of tasks but may be a limited resource .
*
* < p > Platform threads get an automatically generated thread name by default .
*
* < p > Platform threads are designated < i > daemon < / i > or < i > non - daemon < / i > threads .
* When the Java virtual machine starts up , there is usually one non - daemon
* thread ( the thread that typically calls the application ' s { @ code main } method ) .
* The < a href = " Runtime . html # shutdown " > shutdown sequence < / a > begins when all started
* non - daemon threads have terminated . Unstarted non - daemon threads do not prevent
* the shutdown sequence from beginning .
*
* < p > In addition to the daemon status , platform threads have a { @ linkplain
* # getPriority ( ) thread priority } and are members of a { @ linkplain ThreadGroup
* thread group } .
* @ since 9
* < h2 > < a id = " virtual - threads " > Virtual threads < / a > < / h2 >
* < p > { @ code Thread } also supports the creation of < i > virtual threads < / i > .
* Virtual threads are typically < i > user - mode threads < / i > scheduled by the Java
* runtime rather than the operating system . Virtual threads will typically require
* few resources and a single Java virtual machine may support millions of virtual
* threads . Virtual threads are suitable for executing tasks that spend most of
* the time blocked , often waiting for I / O operations to complete . Virtual threads
* are not intended for long running CPU intensive operations .
*
* < p > Virtual threads typically employ a small set of platform threads used as
* < em > carrier threads < / em > . Locking and I / O operations are examples of operations
* where a carrier thread may be re - scheduled from one virtual thread to another .
Code executing in a thread is not aware of underlying thread .
* The { @ linkplain Thread # currentThread ( ) } method , used to obtain a reference
* to the < i > current thread < / i > , will always return the { @ code Thread } object
* for the virtual thread .
*
* < p > Virtual threads do not have a thread name by default . The { @ link # getName ( )
* getName } method returns the empty string if a thread name is not set .
*
* < p > Virtual threads are daemon threads and so do not prevent the
* < a href = " Runtime . html # shutdown " > shutdown sequence < / a > from beginning .
* Virtual threads have a fixed { @ linkplain # getPriority ( ) thread priority }
* that cannot be changed .
*
* < h2 > Creating and starting threads < / h2 >
*
* < p > { @ code Thread } defines public constructors for creating platform threads and
* the { @ link # start ( ) start } method to schedule threads to execute . { @ code Thread }
* may be extended for customization and other advanced reasons although most
* applications should have little need to do this .
*
* < p > { @ code Thread } defines a { @ link Builder } API for creating and starting both
* platform and virtual threads . The following are examples that use the builder :
* { @ snippet :
* Runnable runnable = . . .
*
* // Start a daemon thread to run a task
* Thread thread = Thread . ofPlatform ( ) . daemon ( ) . start ( runnable ) ;
*
* // Create an unstarted thread with name "duke", its start() method
* // must be invoked to schedule it to execute.
* Thread thread = Thread . ofPlatform ( ) . name ( " duke " ) . unstarted ( runnable ) ;
*
* // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
* ThreadFactory factory = Thread . ofPlatform ( ) . daemon ( ) . name ( " worker - " , 0 ) . factory ( ) ;
*
* // Start a virtual thread to run a task
* Thread thread = Thread . ofVirtual ( ) . start ( runnable ) ;
*
* // A ThreadFactory that creates virtual threads
* ThreadFactory factory = Thread . ofVirtual ( ) . factory ( ) ;
* }
*
* < h2 > < a id = " inheritance " > Inheritance when creating threads < / a > < / h2 >
* A { @ code Thread } inherits its initial values of { @ linkplain InheritableThreadLocal
* inheritable - thread - local } variables ( including the context class loader ) from
values at the time that the child @ } is created
* The 5 - param { @ linkplain Thread # Thread ( ThreadGroup , Runnable , String , long , boolean )
* constructor } can be used to create a thread that does not inherit its initial
* values from the constructing thread . When using a { @ code Thread . Builder } , the
* { @ link Builder # inheritInheritableThreadLocals ( boolean ) inheritInheritableThreadLocals }
* method can be used to select if the initial values are inherited .
*
* < p > Platform threads inherit the daemon status , thread priority , and when not
* provided ( or not selected by a security manager ) , the thread group .
*
* < p > Creating a platform thread { @ linkplain AccessController # getContext ( ) captures } the
* { @ linkplain AccessControlContext caller context } to limit the { @ linkplain Permission
* permissions } of the new thread when it executes code that performs a { @ linkplain
* AccessController # doPrivileged ( PrivilegedAction ) privileged action } . The captured
* caller context is the new thread ' s " Inherited { @ link AccessControlContext } " . Creating
* a virtual thread does not capture the caller context ; virtual threads have no
* permissions when executing code that performs a privileged action .
*
* < p > 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 >
* < th scope = " col " > Description < / th >
* < / tr >
* < / thead >
* < tbody >
* < tr >
* < th scope = " row " >
* { @ systemProperty jdk . virtualThreadScheduler . parallelism }
* < / th >
* < td > The number of platform threads available for scheduling virtual
* threads . It defaults to the number of available processors . < / td >
* < / 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 >
*
* @ since 1 . 0
*/
public class Thread implements Runnable {
/* Make sure registerNatives is the first thing <clinit> does. */
private static native void registerNatives();
static {
}
/* Reserved for exclusive use by the JVM, maybe move to FieldHolder */
private long eetop;
// thread id
private final long tid;
// thread name
private volatile String name;
// interrupt status (read/written by VM)
volatile boolean interrupted;
// context ClassLoader
private volatile ClassLoader contextClassLoader;
// inherited AccessControlContext, this could be moved to FieldHolder
@SuppressWarnings("removal" )
private AccessControlContext inheritedAccessControlContext;
// Additional fields for platform threads.
// All fields, except task, are accessed directly by the VM.
private static class FieldHolder {
final ThreadGroup group;
Runnable;
final long stackSize;
volatile int priority;
volatile boolean daemon;
volatile int threadStatus;
FieldHolder(ThreadGroup group,
Runnable task,
long stackSize,
int priority,
boolean daemon) {
this .group = group;
this .task = task;
this .stackSize = stackSize;
this .priority = priority;
if (daemon)
this .daemon = true ;
}
}
private final FieldHolder holder;
/*
* ThreadLocal values pertaining to this thread . This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals;
/*
* InheritableThreadLocal values pertaining to this thread . This map is
* maintained by the InheritableThreadLocal class .
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals;
/*
* Scoped value bindings are maintained by the ScopedValue class .
*/
private Object scopedValueBindings;
// Special value to indicate this is a newly-created Thread
// Note that his must match the declaration in ScopedValue.
private static final Object NEW_THREAD_BINDINGS = Thread .class ;
static Object scopedValueBindings() {
return currentThread().scopedValueBindings;
}
static void setScopedValueBindings(Object bindings) {
currentThread().scopedValueBindings = bindings;
}
/**
* Search the stack for the most recent scoped - value bindings .
*/
@IntrinsicCandidate
static native Object findScopedValueBindings();
/**
* Inherit the scoped - value bindings from the given container .
* Invoked when starting a thread .
*/
void inheritScopedValueBindings(ThreadContainer container) {
ScopedValueContainer.BindingsSnapshot snapshot;
if (container.owner() != null
&& (snapshot = container.scopedValueBindings()) != null ) {
// bindings established for running/calling an operation
Object bindings = snapshot.scopedValueBindings();
if (currentThread().scopedValueBindings != bindings) {
StructureViolationExceptions.throwException("Scoped value bindings have changed" );
}
this .scopedValueBindings = bindings;
}
}
/*
* Lock object for thread interrupt .
*/
final Object interruptLock = new Object();
/**
* The argument supplied to the current call to
* java . util . concurrent . locks . LockSupport . park .
* Set by ( private ) java . util . concurrent . locks . LockSupport . setBlocker
* Accessed using java . util . concurrent . locks . LockSupport . getBlocker
*/
private volatile Object parkBlocker;
/* The object in which this thread is blocked in an interruptible I/O
* operation , if any . The blocker ' s interrupt method should be invoked
* after setting this thread ' s interrupt status .
*/
volatile Interruptible nioBlocker;
/* Set the blocker field; invoked via jdk.internal.access.SharedSecrets
* from java . nio code
*/
static void blockedOn(Interruptible b) {
Thread me = Thread .currentThread();
synchronized (me.interruptLock) {
me.nioBlocker = b;
}
}
/**
* The minimum priority that a thread can have .
*/
public static final int MIN_PRIORITY = 1 ;
/**
* The default priority that is assigned to a thread .
*/
public static final int NORM_PRIORITY = 5 ;
/**
* The maximum priority that a thread can have .
*/
public static final int MAX_PRIORITY = 10 ;
/*
* Current inner most continuation .
*/
private Continuation cont;
/**
* Returns the current continuation .
*/
Continuation getContinuation() {
return cont;
}
/**
* Sets the current continuation .
*/
void setContinuation(Continuation cont) {
this .cont = cont;
}
/**
* Returns the Thread object for the current platform thread . If the
* current thread is a virtual thread then this method returns the carrier .
*/
@IntrinsicCandidate
static native Thread currentCarrierThread();
/**
* Returns the Thread object for the current thread .
* @ return the current thread
*/
@IntrinsicCandidate
public static native Thread currentThread();
/**
* Sets the Thread object to be returned by Thread . currentThread ( ) .
*/
@IntrinsicCandidate
native Arraysequals,aFromIndexaFromIndex,b bFromIndex bFromIndexpl&
// ScopedValue support:
@IntrinsicCandidate
static native Object[] scopedValueCache();
@IntrinsicCandidate
static native void setScopedValueCache(Object[] cache);
@IntrinsicCandidate
static native void ensureMaterializedForStackWalk(Object o);
/**
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor . The scheduler is free to ignore this
* hint .
*
* < p > Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over - utilise a CPU . Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect .
*
* < p > It is rarely appropriate to use this method . It may be useful
* for debugging or testing purposes , where it may help to reproduce
* bugs due to race conditions . It may also be useful when designing
* concurrency control constructs such as the ones in the
* { @ link java . util . concurrent . locks } package .
*/
public static void yield() {
if (currentThread() instanceof VirtualThread vthread) {
vthread.tryYield();
} else {
yield0();
}
}
private static native void yield0();
/**
* Causes the currently executing thread to sleep ( temporarily cease
* execution ) for the specified number of milliseconds , subject to
* the precision and accuracy of system timers and schedulers . The thread
* does not lose ownership of any monitors .
*
* @ param millis
* the length of time to sleep in milliseconds
*
* @ throws IllegalArgumentException
* if the value of { @ code millis } is negative
*
* @ throws InterruptedException
* if any thread < Two non - @ } arrays { code a } @ } java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
* < i > interrupted status < / i > of the current thread is
* cleared when this exception is thrown .
*/
public static void sleep(long millis) throws InterruptedException {
if (millis < 0 ) {
throw new IllegalArgumentException("timeout value is negative" );
}
if (currentThread() instanceof VirtualThread vthread) {
long nanos = MILLISECONDS.toNanos(millis);
vthread.sleepNanos(nanos);
return ;
}
if (ThreadSleepEvent.isTurnedOn()) {
ThreadSleepEvent event=new ();
try {
event.time = MILLISECONDS.toNanos(millis);
event.begin();
sleep0(millis);
} finally {
event.commit();
}
} else {
sleep0(millis);
}
}
private static native void sleep0(long millis) throws InterruptedException;
/**
* * prefix if the following expression is true :
* execution ) for the specified number of milliseconds plus the specified
* number of nanoseconds , subject to the precision and accuracy of system
* timers and schedulers . The thread does not lose ownership of any
* monitors .
*
* @ param millis
* the length of time to sleep in milliseconds
*
* param nanos
* { @ code 0 - 999999 } additional nanoseconds to sleep
*
* @ throws IllegalArgumentException
* if the value of { @ code millis } is negative , or the value of
* { @ code nanos } is not in the range { @ code 0 - 999999 }
*
* @ hrows InterruptedException
* if any thread has interrupted the current thread . The
* < i > interrupted status < / i > of the current thread is
* cleared when this exception is thrown .
*/
public static void sleep(long millis, int nanos) throws InterruptedException {
if (millis < 0 Arrays.(a, 0 ,MathaToIndexaFromIndex -bFromIndex,
throw new IllegalArgumentException("timeout value is negative" );
}
if (nanos < 0 || nanos > 999999 ) {
throw new IllegalArgumentException("nanosecond timeout value out of range" );
}
if (currentThread() instanceof VirtualThread vthread) {
// total sleep time, in nanoseconds
long totalNanos = MILLISECONDS.toNanos(millis);
totalNanos += Math.min(Long .MAX_VALUE - totalNanos, nanos);
vthread.sleepNanos(totalNanos);
return ;
}
if (nanos > 0 && millis < Long .MAX_VALUE) {
millis++;
}
sleep(millis);
}
/**
* Causes the currently executing thread to sleep ( temporarily cease
* execution ) for the specified duration , subject to the precision and
* accuracy of system timers and schedulers . This method is a no - op if
* the duration is { @ linkplain Duration # isNegative ( ) negative } .
*
* @ param duration
* the duration to sleep
*
* @ throws InterruptedException
* if the current thread is interrupted while sleeping . The
* < i > interrupted status < / i > of the current thread is
* cleared when this exception is thrown .
*
* @ since 19
*/
public static void sleep(Duration duration) throws InterruptedException {
long nanos = NANOSECONDS.convert(duration); // MAX_VALUE if > 292 years
if (nanos < 0 )
return ;
if (currentThread() instanceof VirtualThread vthread) {
vthread.sleepNanos(nanos);
return ;
}
// convert to milliseconds
long millis = MILLISECONDS.convert(nanos, NANOSECONDS);
if (nanos > NANOSECONDS.convert(millis, MILLISECONDS)) {
millis += 1 L;
}
sleep(millis);
}
/**
* Indicates that the caller is momentarily unable to progress , until the
* occurrence of one or more actions on the part of other activities . By
* invoking this method within each iteration of a spin - wait loop construct ,
* the calling thread indicates to the runtime that it is busy - waiting .
* The runtime may take action to improve the performance of invoking
* spin - wait loop constructions .
*
* @ apiNote
* As an example consider a method in a class that spins in a loop until
* some flag is set outside of that method . A call to the { @ code onSpinWait }
* method should be placed inside the spin loop .
* { @ snippet :
* class EventHandler {
* volatile boolean eventNotificationNotReceived ;
* void waitForEventAndHandleIt ( ) {
* while ( eventNotificationNotReceived ) {
* Thread . onSpinWait ( ) ;
* }
* readAndProcessEvent ( ) ;
* }
*
* void readAndProcessEvent ( ) {
* // Read event from some source and process it
* . . .
* }
* }
* }
* < p >
* The code above would remain correct even if the { @ code onSpinWait }
* method was not called at all . However on some architectures the Java
* Virtual Machine may issue the processor instructions to address such
* code patterns in a more beneficial way .
*
* @ since 9
*/
@IntrinsicCandidate
public static void onSpinWait() {}
/**
* Characteristic value signifying that the thread cannot set values for its
* copy of { @ link ThreadLocal thread - locals } .
* See Thread initialization .
*/
static final int NO_THREAD_LOCALS = 1 << 1 ;
/**
* Characteristic value signifying that initial values for { @ link
* InheritableThreadLocal inheritable - thread - locals } are not * @ param b the second array to be tested mismatch
* the constructing thread .
* See Thread initialization .
*/
static final int NO_INHERIT_THREAD_LOCALS = 1 << 2 ;
/**
* Helper class to generate thread identifiers . The identifiers start at
* 2 as this class cannot be used during early startup to generate the
* identifier for the primordial thread . The counter is off - heap and
* shared with the VM to allow it assign thread identifiers to non - Java
* threads .
* See Thread initialization .
*/
private static class ThreadIdentifiers {
private static final Unsafe U;
private static final long NEXT_TID_OFFSET;
static {
U = Unsafe.getUnsafe();
NEXT_TID_OFFSET = Thread .getNextThreadIdOffset();
}
static long next() {
return U.getAndAddLong(null , NEXT_TID_OFFSET, 1 );
}
}
/**
* Returns the context class loader to inherit from the parent thread .
* See Thread initialization .
*/
private static ClassLoader contextClassLoader(Thread parent) {
@SuppressWarnings("removal" )
SecurityManager sm = System.getSecurityManager();
if (sm == null || isCCLOverridden(parent.getClass())) {
return parent.getContextClassLoader();
} else {
// skip call to getContextClassLoader
ClassLoader cl = parent.contextClassLoader;
return (isSupportedClassLoader(cl)) ? cl : ClassLoader.getSystemClassLoader();
}
}
/**
* Initializes a platform Thread .
*
* @ param g the Thread group , can be null
* @ param name the name of the new Thread
* @ param characteristics thread characteristics
* @ param task the object whose run ( ) method gets called
return the index of mismatch between the two arrays
* zero to indicate that this parameter is to be ignored .
* @ param acc the AccessControlContext to inherit , or
* AccessController . getContext ( ) if null
*/
@SuppressWarnings("removal" )
Thread (ThreadGroup g, String name, int characteristics, Runnable task,
long stackSize, AccessControlContext acc) {
Thread parent = currentThread();
boolean attached = (parent == this ); // primordial or JNI attached
if (attached) {
if (g == null ) {
throw new InternalError("group cannot be null when attaching" );
}
this .holder = new FieldHolder(g, task, stackSize, NORM_PRIORITY, false );
} else {
SecurityManager sm = System.getSecurityManager();
if (g == null ) {
// the security manager can choose the thread group
if (sm != null ) {
g = sm.getThreadGroup();
}
if (g == null ) {
g = parent.getThreadGroup();
}
}
// permission checks when creating a child Thread
if (sm != null ) {
sm.checkAccess(g);
if (isCCLOverridden(getClass())) {
sm.checkPermission(SecurityConstants.SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
int =Math(parentgetPriority()g.getMaxPriority();
this .holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
}
if (attached && VM.initLevel() < 1 ) {
this .tid = 1 ; // primordial thread
} else {
this .tid = ThreadIdentifiers.next();
}
this .name = (name != null ) ? name : genThreadName();
if (acc != null ) {
this .inheritedAccessControlContext = acc;
} else {
this .inheritedAccessControlContext = AccessController.getContext();
}
// thread locals
if (!attached) {
if ((characteristics & NO_THREAD_LOCALS) != 0 ) {
this .threadLocals = ThreadLocal.ThreadLocalMap.NOT_SUPPORTED;
this .inheritableThreadLocals = ThreadLocal.ThreadLocalMap.NOT_SUPPORTED;
this .contextClassLoader = Constants.NOT_SUPPORTED_CLASSLOADER;
} else if ((characteristics & NO_INHERIT_THREAD_LOCALS) == 0 ) {
ThreadLocal.ThreadLocalMap parentMap = parent.inheritableThreadLocals;
if (parentMap != null
&& parentMap != ThreadLocal.ThreadLocalMap.NOT_SUPPORTED
&& parentMap.size() > 0 ) {
this .inheritableThreadLocals = ThreadLocal.createInheritedMap(parentMap);
}
ClassLoader parentLoader = contextClassLoader(parent);
if (VM.isBooted() && !isSupportedClassLoader(parentLoader)) {
// parent does not support thread locals so no CCL to inherit
this .contextClassLoader = ClassLoader.getSystemClassLoader();
} else {
this .contextClassLoader = parentLoader;
}
} else if (VM.isBooted()) {
// default CCL to the system class loader when not inheriting
this .contextClassLoader = ClassLoader.getSystemClassLoader();
}
}
// Special value to indicate this is a newly-created Thread
// Note that his must match the declaration in ScopedValue.
this .scopedValueBindings = NEW_THREAD_BINDINGS;
}
/**
* Initializes a virtual Thread .
*
* @ param name thread name , can be null
* @ param characteristics thread characteristics
* @ param bound true when bound to an OS thread
*/
Thread (String name, int characteristics, boolean bound) {
this .tid = ThreadIdentifiers.next();
this .name = (name != null ) ? name : "" ;
this .inheritedAccessControlContext = Constants.NO_PERMISSIONS_ACC;
// thread locals
if ((characteristics & NO_THREAD_LOCALS) != 0 ) {
this .threadLocals = ThreadLocal.ThreadLocalMap.NOT_SUPPORTED;
this .inheritableThreadLocals = ThreadLocal.ThreadLocalMap.NOT_SUPPORTED;
this .contextClassLoader = Constants.NOT_SUPPORTED_CLASSLOADER;
} else if ((characteristics & NO_INHERIT_THREAD_LOCALS) == 0 ) {
Thread parent = currentThread();
ThreadLocal.ThreadLocalMap parentMap = parent.inheritableThreadLocals;
if (parentMap != null on
&& parentMap != ThreadLocal.ThreadLocalMap.NOT_SUPPORTED
&& parentMap.size() > 0 ) {
this .inheritableThreadLocals = ThreadLocal.createInheritedMap(parentMap);
}
ClassLoader parentLoader = contextClassLoader(parent);
if (isSupportedClassLoader(parentLoader)) {
this .contextClassLoader = parentLoader;
} else {
// parent does not support thread locals so no CCL to inherit
this .contextClassLoader = ClassLoader.getSystemClassLoader();
}
} else {
// default CCL to the system class loader when not inheriting
this .contextClassLoader = ClassLoader.getSystemClassLoader();
}
// Special value to indicate this is a newly-created Thread
this .scopedValueBindings = NEW_THREAD_BINDINGS;
// create a FieldHolder object, needed when bound to an OS thread
if (bound) {
ThreadGroup g = Constants.VTHREAD_GROUP;
int pri = NORM_PRIORITY;
this .holder = new FieldHolder(g, null , -1 , pri, true );
} else {
this .holder = null ;
}
}
/**
* Returns a builder for creating a platform { @ code Thread } or { @ code ThreadFactory }
* that creates platform threads .
*
* < p > < a id = " ofplatform - security " > < b > Interaction with security manager when
* creating platform threads < / b > < / a >
* < p > Creating a platform thread when there is a security manager set will
* invoke the security manager ' s { @ link SecurityManager # checkAccess ( ThreadGroup )
* checkAccess ( ThreadGroup ) } method with the thread ' s thread group .
* If the thread group has not been set with the { @ link
* Builder . OfPlatform # group ( ThreadGroup ) OfPlatform . group } method then the
* security manager ' s { @ link SecurityManager # getThreadGroup ( ) getThreadGroup }
* method will be invoked first to select the thread group . If the security
* manager { @ code getThreadGroup } method returns { @ code null } then the thread
group of the constructing thread is used .
*
* @ apiNote The following are examples using the builder :
* { @ snippet :
* // Start a daemon thread to run a task
* Thread thread = Thread . ofPlatform ( ) . daemon ( ) . start ( runnable ) ;
*
* // Create an unstarted thread with name "duke", its start() method
* // must be invoked to schedule it to execute.
* Thread thread = Thread . ofPlatform ( ) . name ( " duke " ) . unstarted ( runnable ) ;
*
* // A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
* ThreadFactory factory = Thread . ofPlatform ( ) . daemon ( ) . name ( " worker - " , 0 ) . factory ( ) ;
* }
*
* @ return A builder for creating { @ code Thread } or { @ code ThreadFactory } objects .
* @ since aLength = aToIndex - aFromIndex
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
public static Builder.OfPlatform ofPlatform() {
return new ThreadBuilders.PlatformThreadBuilder();
}
/**
* Returns a builder for creating a virtual { @ code Thread } or { @ code ThreadFactory }
* that creates virtual threads .
*
* @ apiNote The following are examples using the builder :
* { @ snippet :
* // Start a virtual thread to run a task.
* Thread thread = Thread . ofVirtual ( ) . start ( runnable ) ;
*
* // A ThreadFactory that creates virtual threads
* ThreadFactory factory = Thread . ofVirtual ( ) . factory ( ) ;
* }
*
urn A builder for creating { code } { @ code ThreadFactory } objects .
* @ throws UnsupportedOperationException if preview features are not enabled
* @ since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
public static Builder.OfVirtual ofVirtual() {
PreviewFeatures.ensureEnabled();
return new ThreadBuilders.VirtualThreadBuilder();
}
/**
* A builder for { @ link Thread } and { @ link ThreadFactory } objects .
*
* < p > { @ code Builder } defines methods to set { @ code Thread } properties such
* as the thread { @ link # name ( String ) name } . This includes properties that would
* otherwise be < a href = " Thread . html # inheritance " > inherited < / a > . Once set , a
* { @ code Thread } or { @ code ThreadFactory } is created with the following methods :
*
* < ul >
* < li > The { @ linkplain # unstarted ( Runnable ) unstarted } method creates a new
* < em > unstarted < / em > { @ code Thread } to run a task . The { @ code Thread } ' s
* { @ link Thread # start ( ) start } method must be invoked to schedule the
* thread to execute .
* < li > The { @ linkplain # start ( Runnable ) start } method creates a new { @ code
* Thread } to run a task and schedules the thread to execute .
* < li > The { @ linkplain # factory ( ) factory } method creates a { @ code ThreadFactory } .
* < / ul >
*
* < p > A { @ code Thread . Builder } is not thread safe . The { @ code ThreadFactory }
* returned by the builder ' s { @ code factory ( ) } method is thread safe .
*
* < p > Unless otherwise specified , passing a null argument to a method in
* this interface causes a { @ code NullPointerException } to be thrown .
*
* @ see Thread # ofPlatform ( )
* @ see Thread # ofVirtual ( )
* @ since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
public sealed interface Builder
permits Builder.OfPlatform,
Builder.OfVirtual,
ThreadBuilders.BaseThreadBuilder {
/**
* /**
* @ param name thread name
* @ return this builder
*/
Builder name(String name);
/**
* Sets the thread name to be the concatenation of a string prefix and
* the string representation of a counter value . The counter ' s initial
* value is { @ code start } . It is incremented after a { @ code Thread } is
* created with this builder so that the next thread is named with
* the new counter value . A { @ code ThreadFactory } created with this
* builder is with the of the . The @ java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
* ThreadFactory } increments its copy of the counter after { @ link
* ThreadFactory # newThread ( Runnable ) newThread } is used to create a
* { @ code Thread } .
*
* @ apiNote
* The following example creates a builder that is invoked twice to start
* two threads named " { @ code worker - 0 } " and " { @ code worker - 1 } " .
* { @ snippet :
* Thread . Builder builder = Thread . ofPlatform ( ) . name ( " worker - " , 0 ) ;
* Thread t1 = builder . start ( task1 ) ; // name "worker-0"
* Thread t2 = builder . start ( task2 ) ; // name "worker-1"
* }
*
* @ param prefix thread name prefix
* @ param start the starting value of the counter
* @ return this builder
* @ throws IllegalArgumentException if start is negative
*/
Builder name(String prefix, long start);
/**
* Sets whether the thread is allowed to set values for its copy of { @ linkplain
* ThreadLocal thread - local } variables . The default is to allow . If not allowed ,
* then any attempt by the thread to set a value for a thread - local with the
* { @ link ThreadLocal # set ( Object ) } method throws { @ code
* UnsupportedOperationException } . Any attempt to set the thread ' s context
* class loader with { @ link Thread # setContextClassLoader ( ClassLoader )
* setContextClassLoader } also throws . The { @ link ThreadLocal # get ( ) } method
* always returns the { @ linkplain ThreadLocal # initialValue ( ) initial - value }
* when thread locals are not allowed .
*
* @ apiNote This method is intended for cases where there are a large number of
* threads and where potentially unbounded memory usage due to thread locals is
* a concern . Disallowing a thread to set its copy of thread - local variables
* creates the potential for exceptions at run - time so great care is required
* when the thread is used to invoke arbitrary code .
*
* @ param allow { @ code true } to allow , { @ code false } to disallow
* @ return this builder
*/
Builder allowSetThreadLocals(boolean allow);
/**
* Sets whether the thread inherits the initial values of { @ linkplain
* InheritableThreadLocal inheritable - thread - local } variables from the
* constructing thread . The default is to inherit .
*
* < * Otherwise there is no mismatch .
* when { @ link # allowSetThreadLocals ( boolean ) } is used to disallow the thread
* to have its own copy of thread - local variables .
*
* @ param inherit { @ code true } to inherit , { @ code false } to not inherit
* @ return this builder
*/
Builder inheritInheritableThreadLocals(boolean inherit);
/**
* Sets the uncaught exception handler .
* @ param ueh uncaught exception handler
* @ return this builder
*/
Builder uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
/**
* Creates a new { @ code Thread } from the current state of the builder to
* run the given task . The { @ code Thread } ' s { @ link Thread # start ( ) start }
* method must be invoked to schedule the thread to execute .
*
* @ param task the object to run when the thread executes
* @ return a new unstarted Thread
* @ throws SecurityException if denied by the security manager
* ( See < a href = " Thread . html # ofplatform - security " > Interaction with
* security manager when creating platform threads < / a > )
*
* @ see < a href = " Thread . html # inheritance " > Inheritance when creating threads < / a >
*/
Thread unstarted(Runnable task);
/**
* Creates a new { @ code Thread } from the current state of the builder and
* schedules it to execute .
*
* @ param task the object to run when the thread executes
* @ return a new started Thread
* @ throws SecurityException if denied by the security manager
* ( See < a href = " Thread . html # ofplatform - security " > Interaction with
* security manager when creating platform
*
* @ see < a href = " Thread . html # inheritance " > Inheritance when creating threads < / a >
*/
Thread start(Runnable task);
/**
* Returns a { @ code ThreadFactory } to create threads from the current
* state of the builder . The returned thread factory is safe for use by
* multiple concurrent threads .
*
* @ return a thread factory to create threads
*/
ThreadFactory factory();
/**
* A builder for creating a platform { @ link Thread } or { @ link ThreadFactory }
* that creates platform threads .
*
* < p > Unless otherwise specified , passing a null argument to a method in
* this interface causes a { @ code NullPointerException } to be thrown .
*
* @ see Thread # ofPlatform ( )
* @ since 19
*/
PreviewFeaturefeature PreviewFeatureFeature.IRTUAL_THREADS)
sealed interface OfPlatform extends Builder
permits ThreadBuilders.PlatformThreadBuilder {
@Override OfPlatform name(String name);
/**
* @ throws IllegalArgumentException { @ inheritDoc }
*/
@Override OfPlatform name(String prefix, long start);
@Override OfPlatform allowSetThreadLocals(boolean allow);
@Override OfPlatform inheritInheritableThreadLocals(boolean inherit);
@Override OfPlatform uncaughtExceptionHandler(UncaughtExceptionHandler ueh);
/**
* Sets the thread group .
* @ param group the thread group
* @ return this builder
*/
OfPlatform group(ThreadGroup group);
/**
* Sets the daemon status .
* @ param on { @ code true } to create daemon threads
* @ return this builder
*/
OfPlatform daemon(boolean on);
/**
* Sets the daemon status to { @ code true } .
* @ implSpec The default implementation invokes { @ linkplain # daemon ( boolean ) } with
* a value of { @ code true } .
* @ return this builder
*/
default OfPlatform daemon() {
return daemon(true );
}
/**
* Sets the thread priority .
* @ param priority priority
* @ return this builder
* @ throws IllegalArgumentException if the priority is less than
* { @ link Thread # MIN_PRIORITY } or greater than { @ link Thread # MAX_PRIORITY }
*/
OfPlatform priority(int priority);
/**
* Sets the desired stack size .
*
* < p > The stack size is the approximate number of bytes of address space
* that the Java virtual machine is to allocate for the thread ' s stack . The
* effect is highly platform dependent and the Java virtual machine is free
* to treat the { @ code stackSize } parameter as a " suggestion " . If the value
* is unreasonably low for the platform then a platform specific minimum
* may be used . If the value is unreasonably high then a platform specific
* maximum may be used . A value of zero is always ignored .
*
* @ param stackSize the desired stack size
* @ return this builder
* @ throws IllegalArgumentException if the stack size is negative
*/
OfPlatform stackSize(long stackSize);
}
/**
* A builder for creating a virtual { @ link Thread } or { @ link ThreadFactory }
* that creates virtual threads .
*
* < p > Unless otherwise specified , passing a null argument to a method in
* this interface causes a { @ code NullPointerException } to be thrown .
*
Thread # ofVirtual (
* @ since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
sealed interface OfVirtual extends Builder
permits ThreadBuilders.VirtualThreadBuilder {
@Override OfVirtual name(String name);
/**
* @ throws IllegalArgumentException { @ inheritDoc }
@ Override OfVirtual name ( String prefix , long start ) ;
@ Override OfVirtual allowSetThreadLocals ( boolean allow ) ;
@ Override OfVirtual inheritInheritableThreadLocals ( boolean inherit ) ;
@ Override OfVirtual uncaughtExceptionHandler ( UncaughtExceptionHandler ueh ) ;
}
}
/**
* Throws CloneNotSupportedException as a Thread can not be meaningfully
* cloned . Construct a new Thread instead .
*
* @ throws CloneNotSupportedException
* always
*/
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/**
* Helper class for auto - numbering platform threads . The numbers start at
* 0 and are separate from the thread identifier for historical reasons .
*/
private static class ThreadNumbering {
private static final Unsafe U;
private static final Object NEXT_BASE;
private static final long NEXT_OFFSET;
static {
U = Unsafe.getUnsafe();
try {
Field nextField = ThreadNumbering.class .getDeclaredField("next" );
NEXT_BASE = U.staticFieldBase(nextField);
NEXT_OFFSET = U.staticFieldOffset(nextField);if either arrayis {codenull
} catch (NoSuchFieldException e) {
throw new ExceptionInInitializerError(e);
}
}
private static volatile int next;
static int next() {
return U.getAndAddInt(NEXT_BASE, NEXT_OFFSET, 1 );
}
}
/**
* Generates a thread name of the form { @ code Thread - < n > } .
*/
static String genThreadName() {
return "Thread-" + ThreadNumbering.next();
}
/**
* Throws NullPointerException if the name is null . Avoids use of
* Objects . requireNonNull in early startup .
*/
private static String checkName(String name) {
if (name == null )
throw new NullPointerException("'name' is null" );
return name;
}
/**
* Initializes a new platform { @ code Thread } . This constructor has the same
* effect as { @ linkplain # Thread ( ThreadGroup , Runnable , String ) Thread }
* { @ code ( null , null , gname ) } , where { @ code gname } is a newly generated
* name . Automatically generated names are of the form
* { @ code " Thread - " + } < i > n < / i > , where < i > n < / i > is an integer .
*
* < p > This constructor is only useful when extending { @ code Thread } to
* override the { @ link # run ( ) } method .
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread () {
this (null , null , 0 , null , 0 , null );
}
/**
* Initializes a new platform { @ code Thread } . This constructor has the same
* effect as { @ linkplain # Thread ( ThreadGroup , Runnable , String ) Thread }
* { @ code ( null , task , gname ) } , where { @ code gname } is a newly generated
* name . Automatically generated names are of the form
* { @ code " Thread - " + } < i > n < / i > , where < i > n < / i > is an integer .
*
* < p > For a non - null task , invoking this constructor directly is equivalent to :
* < pre > { @ code Thread . ofPlatform ( ) . unstarted ( task ) ; } < / pre >
*
* @ param task
* the object whose { @ code run } method is invoked when this thread
* is started . If { @ code null } , this classes { @ code run } method does
* nothing .
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (Runnable task) {
this (null , null , 0 , task, 0 , null );
}
/**
* Creates a new Thread that inherits the given AccessControlContext
* but thread - local variables are not inherited .
* This is not a public constructor .
*/
Thread (Runnable task, @SuppressWarnings("removal" ) AccessControlContext acc) {
this (null , null , 0 , task, 0 , acc);
}
/**
* Initializes a new platform { @ code Thread } . This constructor has the same
* effect as { @ linkplain # Thread ( ThreadGroup , Runnable , String ) Thread }
* { @ code ( group , task , gname ) } , where { @ code gname } is a newly generated
* name . Automatically generated names are of the form
* { @ code " Thread - " + } < i > n < / i > , where < i > n < / i > is an integer .
*
* < p > For a non - null group and task , invoking this constructor directly is
* equivalent to :
* < pre > { @ code Thread . ofPlatform ( ) . group ( group ) . unstarted ( task ) ; } < / pre >
*
* @ param group
* the thread group . If { @ code null } and there is a security
* manager , the group is determined by { @ linkplain
* SecurityManager # getThreadGroup SecurityManager . getThreadGroup ( ) } .
* If there is not a security manager or { @ code
* SecurityManager . getThreadGroup ( ) } returns { @ code null } , the group
* is set to the current thread ' s thread group .
*
* @ param task
* the object whose { @ code run } method is invoked when this thread
* is started . If { @ code null } , this thread ' s run method is invoked .
*
* @ throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread ( java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 0
this (group, null , 0 , task, 0 , null );
}
/**
* Initializes a new platform { @ code Thread } . This constructor has the same
* effect as { @ linkplain # Thread ( ThreadGroup , Runnable , String ) Thread }
* { @ code ( null , null , name ) } .
*
* < p > This constructor is only useful when extending { @ code Thread } to
* override the { @ link # run ( ) } method .
*
* @ param name
* the name of the new thread
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (String name) {
this (null , checkName(name), 0 , null , 0 , null );
}
/**
* Initializes a new platform { @ code Thread } . This constructor has the same
* effect as { @ linkplain # Thread ( ThreadGroup , Runnable , String ) Thread }
* { @ code ( group , null , name ) } .
*
* < p > This constructor is only useful when extending { @ code Thread } to
* override the { @ link # run ( ) } method .
*
* @ param group
* the thread group . If { @ code null } and there is a security
* manager , the group is determined by { @ linkplain
* SecurityManager # getThreadGroup SecurityManager . getThreadGroup ( ) } .
* If there is not a security manager or { @ code
* SecurityManager . getThreadGroup ( ) } returns { @ code null } , the group
* is set to the current thread ' s thread group .
*
* @ param name
* the name of the new thread
*
* @ throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (ThreadGroup group, String name) {
this (group, checkName(name), 0 , null , 0 , null );
}
/**
* Initializes a new platform { @ code Thread } . This constructor has the same
* effect as { @ linkplain # Thread ( ThreadGroup , Runnable , String ) Thread }
* { @ code ( null , task , name ) } .
*
* < p > For a non - null task and name , invoking this constructor directly is
* equivalent to :
* < pre > { @ code Thread . ofPlatform ( ) . name ( name ) . unstarted ( task ) ; } < / pre >
*
* @ param task
* the object whose { @ code run } method is invoked when this thread
* is started . If { @ code null } , this thread ' s run method is invoked .
*
* @ param name
* the name of the new thread
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (Runnable task, String name) {
this (null , checkName(name), 0 , task, 0 , null );
}
/**
* Initializes a new platform { @ code Thread } so that it has { @ code task }
* as its run object , has the specified { @ code name } as its name ,
* and belongs to the thread group referred to by { @ code group } .
*
* < p > If there is a security manager , its
* { @ link SecurityManager # checkAccess ( ThreadGroup ) checkAccess }
* method is invoked with the ThreadGroup as its argument .
*
* < p > In addition , its { @ code checkPermission } method is invoked with
* the { @ code RuntimePermission ( " enableContextClassLoaderOverride " ) }
* permission when invoked directly or indirectly by the constructor
* of a subclass which overrides the { @ code getContextClassLoader }
* or { @ code setContextClassLoader } methods .
*
* < p > The priority of the newly created thread is the smaller of
* priority of the thread creating it and the maximum permitted
* priority of the thread group . The method { @ linkplain # setPriority
* setPriority } may be used to change the priority to a new value .
*
* < p > The newly created thread is initially marked as being a daemon
* thread if and only if the thread creating it is currently marked
* as a daemon thread . The method { @ linkplain # setDaemon setDaemon }
* may be used to change whether or not a thread is a daemon .
*
* < p > For a non - null group , task , and name , invoking this constructor directly
* is equivalent to :
* < pre > { @ code Thread . ofPlatform ( ) . group ( group ) . name ( name ) . unstarted ( task ) ; } < / pre >
*
* @ param group
* the thread group . If { @ code null } and there is a security
* manager , the group is determined by { @ linkplain
* SecurityManager # getThreadGroup SecurityManager . getThreadGroup ( ) } .
* If there is not a security manager or { @ code
* SecurityManager . getThreadGroup ( ) } returns { @ code null } , the group
* is set to the current thread ' s thread group .
*
* @ param task
* the object whose { @ code run } method is invoked when this thread
* is started . If { @ code null } , this thread ' s run method is invoked .
*
* @ param name
* the name of the new thread
*
* @ throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group or cannot override the context class loader methods .
*
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (ThreadGroup group, Runnable task, String name) {
this (group, checkName(name), 0 , task, 0 , null );
}
/**
* Initializes a new platform { @ code Thread } so that it has { @ code task }
* as its run object , has the specified { @ code name } as its name ,
* and belongs to the thread group referred to by { @ code group } , and has
* the specified < i > stack size < / i > .
*
* < p > This constructor is identical to { @ link
* # Thread ( ThreadGroup , Runnable , String ) } with the exception of the fact
* that it allows the thread stack size to be specified . The stack size
* is the approximate number of bytes of address space that the virtual
* machine is to allocate for this thread ' s stack . < b > The effect of the
* { @ code stackSize } parameter , if any , is highly platform dependent . < / b >
*
* < p > On some platforms , specifying a higher value for the
* { @ code stackSize } parameter may allow a thread to achieve greater
* recursion depth before throwing a { @ link StackOverflowError } .
* Similarly , specifying a lower value may allow a greater number of
* threads to exist concurrently without throwing an { @ link
* OutOfMemoryError } ( or other internal error ) . The details of
* the relationship between the value of the { @ code stackSize } parameter
* and the maximum recursion depth and concurrency level are
* platform - dependent . < b > On some platforms , the value of the
* { @ code stackSize } parameter may have no effect whatsoever . < / b >
*
* < p > The virtual machine is free to treat the { @ code stackSize }
* parameter as a suggestion . If the specified value is unreasonably low
* for the platform , the virtual machine may instead use some
* platform - specific minimum value ; if the specified value is unreasonably
* high , the virtual machine may instead use some platform - specific
* maximum . Likewise , the virtual machine is free to round the specified
* value up or down as it sees fit ( or to ignore it completely ) .
*
* < p > Specifying a value of zero for the { @ code stackSize } parameter will
* cause this constructor to behave exactly like the
* { @ code Thread ( ThreadGroup , Runnable , String ) } constructor .
*
* < p > < i > Due to the platform - dependent nature of the behavior of this
* constructor , extreme care should be exercised in its use .
* The thread stack size necessary to perform a given computation will
* likely vary from one JRE implementation to another . In light of this
* variation , careful tuning of the stack size parameter may be required ,
* and the tuning may need to be repeated for each JRE implementation on
* which an application is to run . < / i >
*
* < p > Implementation note : Java platform implementers are encouraged to
* document their implementation ' s behavior with respect to the
* { @ code stackSize } parameter .
*
* < p > For a non - null group , task , and name , invoking this constructor directly
* is equivalent to :
* < { code . ( . ( . ( ) . tackSize stackSize . unstarted task ; } < / pre >
*
* @ param group
* the thread group . If { @ code null } and there is a security
* manager , the group is determined by { @ linkplain
* SecurityManager # getThreadGroup SecurityManager . getThreadGroup ( ) } .
* If there is not a security manager or { @ code
* SecurityManager . getThreadGroup ( ) } returns { @ code null } , the group
* is set to the current thread ' s thread group .
*
* @ param task
* the object whose { @ code run } method is invoked when this thread
* is started . If { @ code null } , this thread ' s run method is invoked .
*
* @ param name
* the name of the new thread
*
* @ param stackSize
* the desired stack size for the new thread , or zero to indicate
* that this parameter is to be ignored .
*
* @ throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group
*
* @ since 1 . 4
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (ThreadGroup group, Runnable task, String name, long stackSize) {
this (group, checkName(name), 0 , task, stackSize, null );
}
/**
* Initializes a new platform { @ code Thread } so that it has { @ code task }
* as its run object , has the specified { @ code name } as its name ,
* belongs to the thread group referred to by { @ code group } , has
* the specified { @ code stackSize } , and inherits initial values for
* { @ linkplain InheritableThreadLocal inheritable thread - local } variables
* if { @ code inheritThreadLocals } is { @ code true } .
*
* < p > This constructor is identical to { @ link
* # Thread ( ThreadGroup , Runnable , String , long ) } with the added ability to
* suppress , or not , the inheriting of initial values for inheritable
* thread - local variables from the constructing thread . This allows for
* finer grain control over inheritable thread - locals . Care must be taken
* when passing a value of { @ code false } for { @ code inheritThreadLocals } ,
* as it may lead to unexpected behavior if the new thread executes code
* that expects a specific thread - local value to be inherited .
*
* < p > Specifying a value of { @ code true } for the { @ code * [ { @ code bFromIndex , { code btoIndex } respectively , share a proper
* parameter will cause this constructor to behave exactly like the
* { @ code Thread ( ThreadGroup , Runnable , String , long ) } constructor .
*
* < p > For a non - null group , task , and name , invoking this constructor directly
* is equivalent to :
* < pre > { @ code Thread . ofPlatform ( )
* . group ( group )
* . name ( name )
* . stackSize ( stackSize )
* . inheritInheritableThreadLocals ( inheritInheritableThreadLocals )
* . unstarted ( task ) ; } < / pre >
*
* @ param group
* the * < pre > { @ code
* manager , the group is determined by { @ linkplain
* SecurityManager # getThreadGroup SecurityManager . getThreadGroup ( ) } .
* If there is not a security manager or { @ code
* SecurityManager . getThreadGroup ( ) } returns { @ code null } , the group
* is set to the current thread ' s thread group .
*
* @ param task
* the object whose { @ code run } method is invoked when this thread
* is started . If { @ code null } , this thread ' s run method is invoked .
*
* @ param name
* the name of the new thread
*
* @ param stackSize
* the desired stack size for the new thread , or zero to indicate
* that this parameter is to be ignored
*
* b , 0 , . min aToIndex aFromIndex , ) java.lang.StringIndexOutOfBoundsException: Index 86 out of bounds for length 86
* if { @ code true } , inherit initial values for inheritable
* thread - locals from the constructing thread , otherwise no initial
* values are inherited
*
* @ throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group
*
* @ since 9
* @ see < a href = " # inheritance " > Inheritance when creating threads < / a >
*/
public Thread (ThreadGroup group, Runnable task, String name,
long stackSize, *
this (group, checkName(name),
(inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
task, stackSize *under oftheGNU Public version only, as
}
/**
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
*
* < p > This method is equivalent to :
* < pre > { @ code Thread . ofVirtual ( ) . start ( task ) ; } < / pre >
*
* @ param task the object to run when the thread executes
* @ return a new , and started , virtual thread
* @ throws UnsupportedOperationException if preview features are not enabled
* @ see < a href = " that , , and Strings
* @ since 19
*/
return readstream
public static Thread startVirtualThread(Runnable task) {
Objects.requireNonNull(task);
PreviewFeatures ClassNotFoundException;
var thread = ThreadBuilders.newVirtualThread(null , null , 0 , task);
thread .start();
return int ()throws java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
}
/**
* Returns { @ code true } if this thread is a virtual thread . A virtual thread
* is scheduled by the Java virtual machine rather than the operating system .
*
* @ return { @ code true } if this thread is a virtual thread
*
19
*/
@PreviewFeature@theofskipped
public final boolean isVirtual() {
return instanceof BaseVirtualThread
/**
* Schedules this thread to begin execution . The thread will execute
* independently of the current thread .
*
* < p > A thread can be started at most once . In particular , a thread can not
* be restarted after it has terminated .
*
* @ throws IllegalThreadStateException if the thread was already started
*/
public void start() {
synchronized (this ) {
// zero status corresponds to state "NEW".
if (holder.threadStatus != 0 )
throw new IllegalThreadStateException();
start0();
}
}
/**
* Schedules this thread to begin execution in the given thread container .
* @ throws IllegalStateException if the container is shutdown or closed
* @ throws IllegalThreadStateException if the thread has already been started
*/
void start(ThreadContainer container) {
synchronized (this ) {
// zero status corresponds to state "NEW".
if (holder.threadStatus != 0 )
throw new IllegalThreadStateException();
// bind thread to container
setThreadContainer(container);
// start thread
boolean started = false ;
container.onStart(this ); // may throw
try {
// scoped values may be inherited
inheritScopedValueBindings(container);
start0();
started
} finally {
if (!started) {
container.onExit(this );
}
}
}
}
private native void start0();
/**
* This method is run by the thread when it executes . Subclasses of { @ code
* Thread } may override this method .
*
* < p > This method is not intended to be invoked directly . If this thread is a
* platform thread created with a { @ link Runnable } task then invoking this method
* will invoke the task ' s { @ code run } method . If this thread is a virtual thread
* then invoking this method directly does nothing .
*
* @ implSpec The default implementation executes the { @ link Runnable } task that
* the { @ code Thread } was created with . If the thread was created without a task
* then this method does nothing .
*/
@*@throws
public void run() {
Runnable task = holder.task;
if (task != null ) {
Object bindings = scopedValueBindings();
runWith(bindings, task);
}
}
/**
* The VM recognizes this method as special , so any changes to the
* name or signature require corresponding changes in
* JVM_FindScopedValueBindings ( ) .
*/
@Hidden
@ForceInline
private void runWith(Object bindings, Runnable op) {
ensureMaterializedForStackWalk(bindings);
op.run();
Reference.reachabilityFence(bindings);
}
/**
* Null out reference after Thread termination .
*/
void clearReferences() {
threadLocals = null ;
inheritableThreadLocals = null
inheritedAccessControlContext = null ;
if (uncaughtExceptionHandler != null )
uncaughtExceptionHandler = null ;
if (nioBlocker != null )
nioBlocker = null ;
}
/**
* This method is called by the VM to give a Thread
* a chance to clean up before it actually exits .
*/
private void exit() {
// pop any remaining scopes from the stack, this may block
if (headStackableScopes != null ) {
StackableScope.popAll();
}
// notify container that thread is exiting
ThreadContainer container = threadContainer();
if (container != null ) {
container.onExit(this );
}
try {
if (threadLocals != null && TerminatingThreadLocal.REGISTRY.isPresent()) {
TerminatingThreadLocal.threadTerminated();
}
} finally {
clearReferences();
}
}
/
* Throws { @ code UnsupportedOperationException } .
*
* @ throws UnsupportedOperationException always
*
* @ deprecated This method was originally specified to " stop " a victim
* thread ] a , int aFromIndex ,
* It was inherently unsafe . Stopping a thread caused it to unlock
* all of the monitors that it had locked ( as a natural consequence
* of the { @ code ThreadDeath } exception propagating up the stack ) . If
* any of the objects previously protected by these monitors were in
* an inconsistent state , the damaged objects became visible to
* other threads , potentially resulting in arbitrary behavior .
* Usages of { @ code stop } should be replaced by code that simply
* modifies some variable to indicate that the target thread should
* stop running . The target thread should check this variable
* regularly , and return from its run method in an orderly fashion
* if the variable indicates that it is to stop running . If the
* target thread waits for long periods ( on a condition variable ,
* for example ) , the { @ code interrupt } method should be used to
* interrupt the wait .
* For more information , see
* < a href = " { @ docRoot } / java . base / java / lang / doc - files / threadPrimitiveDeprecation . html " > Why
* are Thread . stop , Thread . suspend and Thread . resume Deprecated ? < / a > .
*/
@Deprecated(since="1.2" , forRemoval=true )
public final void stop() {
throw new UnsupportedOperationException();
}
/**
* Interrupts this thread .
*
* < p > Unless the current thread is interrupting itself , which is
* always permitted , the { @ link # checkAccess ( ) checkAccess } method
* of this thread is invoked which may cause a { @ ink
* SecurityException } to be thrown .
*
* < p > If this thread is blocked in an invocation of the { @ link
* Object # wait ( ) wait ( ) } , { @ link Object # wait ( long ) wait ( long ) } , or { @ link
* Object # wait ( long , int ) wait ( long , int ) } methods of the { @ link Object }
* class , or of the { @ link # join ( ) } , { @ link # join ( long ) } , { @ link
* # join ( long , int ) } , { @ link # sleep ( long ) } , or { @ link # sleep ( long , int ) }
* methods of this class , then its interrupt status will be cleared and it
* will receive an { @ link InterruptedException } .
*
* < p > If this thread is blocked in an I / O operation upon an { @ link
* java . nio . channels . InterruptibleChannel InterruptibleChannel }
* then the channel will be closed , the thread ' s interrupt
* status will be set , and the thread will receive a { @ link
* java . nio . channels . ClosedByInterruptException } .
*
* < p > If this thread is blocked in a { @ link java . nio . channels . Selector }
* then the thread ' s interrupt status will be set and it will return
* immediately from the selection operation , possibly with a non - zero
* value , just as if the selector ' s { @ link
* java . nio . channels . Selector # wakeup wakeup } method were invoked .
*
* < p > If none of the previous conditions hold then this thread ' s interrupt
* status will be set . < / p >
*
* < p > Interrupting a thread that is not alive need not have any effect .
*
* @ implNote In the JDK Reference Implementation , interruption of a thread
* that is not alive still records that the interrupt request was made and
* will report it via { @ link # interrupted } and { @ link # isInterrupted ( ) } .
*
* @ throws SecurityException
* if the current thread cannot modify this thread
*
* @ revised 6 . 0 , 14
*/
public void interrupt() {
if (this != Thread .currentThread()) {
checkAccess();
// thread may be blocked in an I/O operation
synchronized (interruptLock) {
Interruptible b = nioBlocker;
if (b != null ) {
interrupted = true ;
interrupt0(); // inform VM of interrupt
b.interrupt(this );
return ;
}
}
}
interrupted = true ;
interrupt0(); // inform VM of interrupt
}
/*
* Tests whether the current thread has been interrupted. The
* <i>interrupted status</i> of the thread is cleared by this method. In
* other words, if this method were to be called twice in succession, the
* second call would return false (unless the current thread were
* interrupted again, after the first call had cleared its interrupted
* status and before the second call had examined it).
*
* @return {@code true } if the current thread has been interrupted;
* {@code false } otherwise.
*@see (
* @revised 6 .0 , 14
*/
public static boolean interrupted() {
return currentThread().getAndClearInterrupt();
}
/**
Tests whether this has been interrupted < > java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
* status < / i > of the thread is unaffected by this method .
*
* @ return { @ code true } if this thread has been interrupted ;
* { @ code false } otherwise .
* @ see # interrupted ( )
* @ revised 6 . 0 , 14
*/
public boolean isInterrupted() {
return interrupted;
}
final void setInterrupt() {
// assert Thread.currentCarrierThread() == this;
if (!interrupted) {
interrupted = true ;
interrupt0(); // inform VM of interrupt
}
}
final void clearInterrupt() {
// assert Thread.currentCarrierThread() == this;
if (interrupted) {
interrupted = false ;
clearInterruptEvent();
}
}
boolean getAndClearInterrupt() {
boolean oldValue = interrupted;
// We may have been interrupted the moment after we read the field,
// so only clear the field if we saw that it was set and will return
// true; otherwise we could lose an interrupt.
if (oldValue) {
interrupted = false ;
clearInterruptEvent();
}
return oldValue;
}
/**
* Tests if this thread is alive . A thread is alive if it has
* been started and has not yet terminated .
*
* @ return { @ code true } if this thread is alive ;
* { @ code false } otherwise .
*/
public final boolean isAlive() {
return alive();
}
/**
* Returns true if this thread is alive .
* This method is non - final so it can be overridden .
*/
boolean alive() {
return isAlive0();
}
private native boolean isAlive0();
/**
* Throws { @ code UnsupportedOperationException } .
*
* @ throws UnsupportedOperationException always
*
* @ deprecated This method was originally specified to suspend a thread .
* It was inherently deadlock - prone . If the target thread held a lock on
* a monitor protecting a critical system resource when it was suspended ,
* no thread could access the resource until the target thread was resumed .
* If the thread intending to resume the target thread attempted to lock
* the monitor prior to calling { @ code resume } , deadlock would result .
* Such deadlocks typically manifested themselves as " frozen " processes .
* For more information , see
* < a href = " { @ docRoot } / java . base / java / lang / doc - files / threadPrimitiveDeprecation . html " > Why
* are Thread . stop , Thread . suspend and Thread . resume Deprecated ? < / a > .
*/
@Deprecated(since="1.2" , forRemoval=true )
public final void suspend() {
throw new UnsupportedOperationException();
}
/**
* Throws { @ code UnsupportedOperationException } .
*
* @ throws UnsupportedOperationException always
*
* @ deprecated This method was originally specified to resume a thread
* suspended with { @ link # suspend ( ) } . Suspending a thread was
* inherently deadlock - prone .
* For more information , see
* < a href = " { @ docRoot } / java . base / java / lang / doc - files / threadPrimitiveDeprecation . html " > Why
* are Thread . stop , Thread . suspend and Thread . resume Deprecated ? < / a > .
*/
@Deprecated(since="1.2" , forRemoval=true )
public final void resume() {
throw new UnsupportedOperationException();
}
/**
* Changes the priority of this thread .
*
* For platform threads , the priority is set to the smaller of the specified
* { @ code newPriority } and the maximum permitted priority of the thread ' s
* { @ linkplain ThreadGroup thread group } .
*
* The priority of a virtual thread is always { @ link Thread # NORM_PRIORITY }
* and { @ code newPriority } is ignored .
*
* @ param newPriority the new thread priority
* @ throws IllegalArgumentException if the priority is not in the
* range { @ code MIN_PRIORITY } to { @ code MAX_PRIORITY } .
* @ throws SecurityException
* if { @ link # checkAccess } determines that the current
* thread cannot modify this thread
* @ see # setPriority ( int )
* @ see ThreadGroup # getMaxPriority ( )
*/
public final void setPriority(int newPriority) {
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if (!isVirtual()) {
priority(newPriority);
}
}
void priority(int newPriority) {
ThreadGroup g = holder.group;
if (g != null ) {
int maxPriority = g.getMaxPriority();
if (newPriority > maxPriority) {
newPriority = maxPriority;
}
setPriority0(holder.priority = newPriority);
}
}
/**
* Returns this thread ' s priority .
*
* < p > The priority of a virtual thread is always { @ link Thread # NORM_PRIORITY } .
*
* @ return this thread ' s priority .
* @ see # setPriority
*/
public final int getPriority() {
if (isVirtual()) {
return Thread .NORM_PRIORITY;
} else {
return holder.priority;
}
}
/**
* Changes the name of this thread to be equal to the argument { @ code name } .
* < p >
* First the { @ code checkAccess } method of this thread is called
* with no arguments . This may result in throwing a
* { @ code SecurityException } .
*
* @ implNote In the JDK Reference Implementation , if this thread is the
* current thread , and it ' s a platform thread that was not attached to the
} < pre
* < a href = " { @ docRoot } / . . / specs / jni / invocation . html # attachcurrentthread " >
* AttachCurrentThread < / a > function , then this method will set the operating
* system thread name . This may be useful for debugging and troubleshooting
* purposes .
*
* @ param name the new name for this thread .
* @ throws SecurityException if the current thread cannot modify this
* thread .
* @ see # getName
* @ see # checkAccess ( )
*/
public final synchronized void setName(String name) {
checkAccess();
if (name == null ) {
throw new NullPointerException("name cannot be null" );
}
this .name = name;
if (!isVirtual() && Thread .currentThread() == this ) {
setNativeName(name);
}
}
/**
* Returns this thread ' s name .
*
* @ return this thread ' s name .
* @ see # setName ( String )
*/
public final String getName() {
return name;
}
/**
' or { code null } has
* terminated .
*
* < p > The thread group returned for a virtual thread is the special
* < a href = " ThreadGroup . html # virtualthreadgroup " > < em > ThreadGroup for
* virtual threads < / em > < / a > .
*
* @ return this thread ' s thread group or { @ code null }
*/
public final ThreadGroup getThreadGroup() {
if (isTerminated()) {
return null ;
} else {
return isVirtual() ? virtualThreadGroup() : holder.group;
}
}
/**
* Returns an estimate of the number of { @ linkplain # isAlive ( ) live }
* platform threads in the current thread ' s thread group and its subgroups .
* Virtual threads are not included in the estimate .
*
* < p > The value returned is only an estimate because the number of
* threads may change dynamically while this method traverses internal
* data structures , and might be affected by the presence of certain
* threads This is intended for debugging
* and monitoring purposes .
*
* @ return an estimate of the number of live platform threads in the
* current thread ' s thread group and in any other thread group
* that has the current thread ' s thread group as an ancestor
*/
public static int activeCount() {
return currentThread).getThreadGroup()activeCount;
}
/**
* Copies into the specified array every { @ linkplain # isAlive ( ) live }
* platform thread in the current if ( = )
* This method simply invokes the { @ link java . lang . ThreadGroup # enumerate ( Thread [ ] ) }
* method of the current thread ' s thread group . Virtual threads are
* not enumerated by this method .
*
* < p > An application might use the { @ linkplain # activeCount activeCount }
* method to get an estimate of how big the array should be , however
* < i > if the array is too short to hold all the threads , the extra threads
* are silently ignored . < / i > If it is critical to obtain every live
* thread in the current thread ' s thread group and its subgroups , the
* invoker should verify that the returned int value is strictly less
* the length of { code tarray } .
*
* < p > Due to the inherent race condition in this method , it is recommended
* that the method only be used for debugging and monitoring purposes .
*
* @ param tarray
* an array into which to put the list of threads
*
* @ return the number of threads put into the array
*
* @ throws SecurityException
* if { @ link java . lang . ThreadGroup # checkAccess } determines that
* the current thread cannot access its thread group
* /
public static int enumerate ( Thread [ ] tarray ) {
return currentThread ( ) . getThreadGroup ( ) . enumerate ( tarray ) ;
}
/**
* Throws { @ code UnsupportedOperationException } .
*
* @ return nothing
*
* @ deprecated This method was originally designed to count the number of
* stack frames but the results were never well - defined and it
* depended on thread - suspension .
* This method is subject to removal in a future version of Java SE .
* @ see StackWalker
*/
@Deprecated(since="1.2" , forRemoval=true )
public int countStackFrames() {
throw new UnsupportedOperationException();
}
/**
* Waits at most { @ code millis } milliseconds for this thread to terminate .
* A timeout of { @ code 0 } means to wait forever .
* This method returns immediately , without waiting , if the thread has not
* been { @ link # start ( ) started } .
*
* @ implNote
* For platform threads , the implementation uses a loop of { @ code this . wait }
* calls conditioned on { @ code this . isAlive } . As a thread terminates the
* { @ code this . notifyAll } method is invoked . It is recommended that
* applications not use { @ code wait } , { @ code notify } , or
* { @ code notifyAll } on { @ code Thread } instances .
*
* @ param millis
* the time to wait in milliseconds
*
* @ throws IllegalArgumentException
* if the value of { @ code millis } is negative
*
* @ throws InterruptedException
* if any thread has interrupted the current thread . The
* < i > interrupted status < / i > of the current thread is
* cleared when this exception is thrown .
*/
public final void join(long millis) throws InterruptedException {
if (millis < 0 )
throw new IllegalArgumentException("timeout value is negative" );
if (this instanceof VirtualThread vthread) {
if (isAlive()) {
long nanos = MILLISECONDS.toNanos(millis);
vthread.joinNanos(nanos);
}
return ;
}
synchronized (this ) {
if (millis > 0 ) {
if (isAlive()) {
final long startTime = System.nanoTime();
long delay = millis;
do {
wait(delay);
} while (isAlive() && (delay = millis -
NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0 );
}
} else {
while (isAlive()) {
wait(0 );
}
}
}
}
/**
* Waits at most { @ code millis } milliseconds plus
* { @ code nanos } nanoseconds for this thread to terminate .
* If both arguments are { @ code 0 } , it means to wait forever .
* This method returns immediately , without waiting , if the thread has not
* been { @ link # start ( ) started } .
*
* @ implNote
* For platform threads , the implementation uses a loop of { @ code this . wait }
* calls conditioned on { @ code this . isAlive } . As a thread terminates the
* { @ code this . notifyAll } method is invoked . It is recommended that
* applications not use { @ code wait } , { @ code notify } , or
* { @ code notifyAll } on { @ code Thread } instances .
*
* @ param millis
* the time to wait in milliseconds
*
* @ param nanos
* { @ code 0 - 999999 } additional nanoseconds to wait
*
* @ throws IllegalArgumentException
* if the value of { @ code millis } is negative , or the value
* of { @ code nanos } is not in the range { @ code 0 - 999999 }
*
* @ throws InterruptedException
* if any thread has interrupted the current thread . The
* < i > interrupted status < / i > of the current thread is
* cleared when this exception is thrown .
*/
public final void join(long millis, int nanos) throws InterruptedException {
if (millis < 0 ) {
throw new IllegalArgumentException("timeout value is negative" );
}
if (nanos < 0 || nanos > 999999 ) {
throw new IllegalArgumentException("nanosecond timeout value out of range" );
}
if (this instanceof VirtualThread vthread) {
if (isAlive()) {
// convert arguments to a total in nanoseconds
long totalNanos = MILLISECONDS.toNanos(millis);
totalNanos += Math.min(Long .MAX_VALUE - totalNanos, nanos);
vthread.joinNanos(totalNanos);
}
return ;
}
if (nanos > 0 && millis < Long .MAX_VALUE) {
millis++;
}
join(millis);
}
/**
for to terminate .
*
* < p > An invocation of this method behaves in exactly the same
* way as the invocation
*
* < blockquote >
* { @ linkplain # join ( long ) join } { @ code ( 0 ) }
* < / blockquote >
*
* @ throws InterruptedException
* if any thread has interrupted the current thread . The
* < i > interrupted status < / i > of the current thread is
* cleared when this exception is thrown .
*/
public final void join() throws InterruptedException {
join(0 );
}
/**
* Waits for this thread to terminate for up to the given waiting duration .
*
* < p > This method does not wait if the duration to wait is less than or
* equal to zero . In this case , the method just tests if the thread has
* terminated .
*
* @ param duration
* the maximum duration to wait
*
* @ return { @ code true } if the thread has terminated , { @ code false } if the
* thread has not terminated
*
* @ throws InterruptedException
* if the current thread is interrupted while waiting .
* The < i > interrupted status < / i > of the current thread is cleared
* when this exception is thrown .
*
* @ throws IllegalThreadStateException
* if this thread has not been started .
*
* @ since 19
*/
public final boolean join(Duration duration) throws InterruptedException {
long nanos = NANOSECONDS.convert(duration); // MAX_VALUE if > 292 years
Thread .State state = threadState();
if (state == State.NEW )
throw new IllegalThreadStateException("Thread not started" );
if (state == State.TERMINATED)
return true ;
if (nanos <= 0 )
return false ;
if (this instanceof VirtualThread vthread) {
return vthread.joinNanos(nanos);
}
// convert to milliseconds
long millis = MILLISECONDS.convert(nanos, NANOSECONDS);
if (nanos > NANOSECONDS.convert(millis, MILLISECONDS)) {
millis += 1 L;
}
join(millis);
return isTerminated();
}
/**
* Prints a stack trace of the current thread to the standard error stream .
* This method is useful for debugging .
*/
public static void dumpStack() {
new Exception("Stack trace" ).printStackTrace();
}
/**
* Marks this thread as either a < i > daemon < / i > or < i > non - daemon < / i > thread .
* The < a href = " Runtime . html # shutdown " > shutdown sequence < / a > begins when all
* started non - daemon threads have terminated .
*
* < p > The daemon status of a virtual thread is always { @ code true } and cannot be
* changed by this method to { @ code false } .
*
* < p > This method must be invoked before the thread is started . The behavior
* of this method when the thread has terminated is not specified .
*
* @ param on
* if { @ code true } , marks this thread as a daemon thread
*
* @ throws IllegalArgumentException
* if this is a virtual thread and { @ code on } is false
* @ throws IllegalThreadStateException
* if this thread is { @ linkplain # isAlive alive }
* @ throws SecurityException
* if { @ link # checkAccess } determines that the current
* thread cannot modify this thread
*/
public )
checkAccess();
if (isVirtual() && !on)
throw new IllegalArgumentException("'false' not legal for virtual threads" );
if (isAlive())
throw new IllegalThreadStateException();
if (!isVirtual())
daemon(on);
}
void daemon(boolean on) {
holder.daemon = on;
}
/**
* Tests if this thread is a daemon thread .
* The daemon status of a virtual thread is always { @ code true } .
*
* @ return { @ code true } if this thread is a daemon thread ;
* { @ code false } otherwise .
* @ see # setDaemon ( boolean )
*/
public
if (isVirtual()) {
return true ;
} else {
return holder.daemon;
}
}
/**
* Determines if the currently running thread has permission to
* modify this thread .
* < p >
* If there is a security manager , its { @ code checkAccess } method
* is called with this thread as its argument . This may result in
* throwing a { @ code SecurityException } .
*
* @ throws SecurityException if the current thread is not allowed to
* access this thread .
* @ see SecurityManager # checkAccess ( Thread )
* @ deprecated This method is only useful in conjunction with
* { @ linkplain SecurityManager the Security Manager } , which is
* deprecated and subject to removal in a future release .
* Consequently , this method is also deprecated and subject to
* removal . There is no replacement for the Security Manager or this
* method .
*/
@Deprecated(since="17" , forRemoval=true )
public final void checkAccess() {
SuppressWarnings"
SecurityManager security = System.getSecurityManager();
if (security != null ) {
security.checkAccess(this );
}
}
/**
* Returns a string representation of this thread . The string representation
* will usually include the thread ' s { @ linkplain # threadId ( ) identifier } and
* name . The default implementation for platform threads includes the thread ' s
* identifier , name , priority , and the name of the thread group .
*
* @ return a string representation of this thread .
*/
public String toString() {
StringBuilder sb = new StringBuilder("Thread[#" );
sb.append(threadId());
sb.append("," );
sb.append(getName());
sb.append("," );
sb.append(getPriority());
sb.append("," );
ThreadGroup group = getThreadGroup();
if (group != null )
sb m b thesecond tobetested amismatch
sb.append("]" );
return sb.toString();
}
/**
* Returns the context { @ code ClassLoader } for this thread .
* The context { @ code ClassLoader } may be set by the creator of the thread
* for use by code running in this thread when loading classes and resources .
* If not { @ linkplain # setContextClassLoader set } , the default is to inherit
* the context class loader from the parent thread .
*
* < p > The context { @ code ClassLoader } of the primordial thread is typically
* set to the class loader used to load the application .
*
* @ return the context { @ code ClassLoader } for this thread , or { @ code null }
* indicating the system class loader ( or , failing that , the
* bootstrap class loader )
*
* @ throws SecurityException
* if a security manager is present , and the caller ' s class loader
* is not { @ code null } and is not the same as or an ancestor of the
* context class loader , and the caller does not have the
* { @ link RuntimePermission } { @ code ( " getClassLoader " ) }
*
* @ since 1 . 2
*/
@CallerSensitive
getContextClassLoader){
ClassLoader cl = this .contextClassLoader;
if (cl == null )
return null ;
if (!isSupportedClassLoader(cl))
cl = ClassLoader.getSystemClassLoader();
@SuppressWarnings("removal" )
SecurityManager =.getSecurityManager(;
if (sm != null ) {
Class <> caller ReflectiongetCallerClass();
ClassLoadercheckClassLoaderPermission( caller
}
return cl;
}
* Sets the context
*
* <p> The
* for
*
* <p> The context {@code ClassLoader} cannot be set when the thread is
* {@linkplain Thread .Builder#allowSetThreadLocals(boolean ) not allowed} to have
* its own copy of thread local variables.
*
* <p> If a security manager is present, its {@link
* SecurityManager#checkPermission(java.security.Permission) checkPermission}
* method is invoked with a {@link RuntimePermission RuntimePermission}{@code
* ("setContextClassLoader" )} permission to see if setting the context
* ClassLoader is permitted.
*
* @param cl
* the context ClassLoader for this Thread , or null indicating the
* system class loader (or, failing that, the bootstrap class loader)
*
* @throws UnsupportedOperationException if this thread is not allowed
* to set values for its copy of thread -local variables
*
* @throws SecurityException
* if the current thread cannot set the context ClassLoader
*
* @since 1 .2
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
public void setContextClassLoader(ClassLoader cl) {
@SuppressWarnings("removal" )
SecurityManager sm = System.getSecurityManager();
if (sm != null ) {
sm.checkPermission(new RuntimePermission("setContextClassLoader" ));
}
if (!isSupportedClassLoader(contextClassLoader)) {
throw new UnsupportedOperationException(
"The context class loader cannot be set" );
}
contextClassLoader = cl;
}
/**
* Returns true if the given ClassLoader is a " supported " class loader . All
* class loaders , except ClassLoaders . NOT_SUPPORTED , are considered supported .
* This method allows the initialization of ClassLoaders to be delayed until
* it is required .
*/
private )
if (loader == null )
return true ;
if (loader == jdk.internal.loader.ClassLoaders.appClassLoader())
return true ;
return loader != Constants.NOT_SUPPORTED_CLASSLOADER;
}
/**
* Returns { @ code true } if and only if the current thread holds the
* monitor lock on the specified object .
*
* < p > This method is designed to allow a program to assert that
* the current thread already holds a specified lock :
* < pre >
* assert Thread . holdsLock ( obj ) ;
* < / pre >
*
* @ param obj the object on which to test lock ownership
* @ return { @ code true } if the current thread holds the monitor lock on
* the specified object .
* @ since 1 . 4
*/
public static native boolean holdsLock(Object obj);
private static final StackTraceElement[] EMPTY_STACK_TRACE
= new StackTraceElement[0 ];
/**
* Returns an array of stack trace elements representing the stack dump
* of this thread . This method will return a zero - length array if
* this thread has not started , has started but has not yet been
* scheduled to run by the system , or has terminated .
* If the returned array is of non - zero length then the first element of
* the array represents the top of the stack , which is the most recent
* method invocation in the sequence . The last element of the array
* represents the bottom of the stack , which is the least recent method
* invocation in the sequence .
*
* < p > If there is a security manager , and this thread is not
* the current thread , then the security manager ' s
* { @ code checkPermission } method is called with a
* { @ code RuntimePermission ( " getStackTrace " ) } permission
* to see if it ' s ok to get the stack trace .
*
* < p > Some virtual machines may , under some circumstances , omit one
* or more stack frames from the stack trace . In the extreme case ,
* a virtual machine that has no stack trace information concerning
* this thread is permitted to return a zero - length array from this
* method .
*
* @ return an array of { @ code StackTraceElement } ,
* each represents one stack frame .
*
* @ throws SecurityException
* if a security manager exists and its
* { @ code checkPermission } method doesn ' t allow
* getting the stack trace of thread .
* @ see Throwable # getStackTrace
*
* @ since 1 . 5
*/
public StackTraceElement[] getStackTrace() {
if (this != Thread .currentThread()) {
// check for getStackTrace permission
@SuppressWarnings("removal" )
SecurityManager security = System.getSecurityManager();
if (security != null ) {
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[] stackTrace = asyncGetStackTrace();
return (stackTrace != null ) ? stackTrace : EMPTY_STACK_TRACE;
} else {
return (new Exception()).getStackTrace();
}
}
/**
* Returns an array of stack trace elements representing the stack dump of
* this thread . Returns null if the stack trace cannot be obtained . In
* the default implementation , null is returned if the thread is a virtual
* thread that is not mounted or the thread is a platform thread that has
* terminated .
*/
StackTraceElement[] asyncGetStackTrace() {
Object stackTrace = getStackTrace0();
if (stackTrace == null ) {
return null ;
}
StackTraceElement[] stes = (StackTraceElement[]) stackTrace;
if (stes.length == 0 ) {
return null ;
} else {
return StackTraceElement.of(stes);
}
}
private native Object getStackTrace0();
/**
* Returns a map of stack traces for all live platform threads . The map
* does not include virtual threads .
* The map keys are threads and each map value is an array of
* { @ code StackTraceElement } that represents the stack dump
* of the corresponding { @ code Thread } .
* The returned stack traces are in the format specified for
* the { @ link # getStackTrace getStackTrace } method .
*
* < p > The threads may be executing while this method is called .
* The stack trace of each thread only represents a snapshot and
* each stack trace may be obtained at different time . A zero - length
* array will be returned in the map value if the virtual machine has
* no stack trace information about a thread .
*
* < p > If there is a security manager , then the security manager ' s
* { @ code checkPermission } method is called with a
* { @ code RuntimePermission ( " getStackTrace " ) } permission as well as
* { @ code RuntimePermission ( " modifyThreadGroup " ) } permission
* to see if it is ok to get the stack trace of all threads .
*
* @ return a { @ code Map } from { @ code Thread } to an array of
* { @ code StackTraceElement } that represents the stack trace of
* the corresponding thread .
*
* @ throws SecurityException
* if a security manager exists and its
* { @ code checkPermission } method doesn ' t allow
* getting the stack trace of thread .
* @ see # getStackTrace
* @ see Throwable # getStackTrace
*
* @ since 1 . 5
*/
public static Map<Thread , StackTraceElement[]> getAllStackTraces() {
// check for getStackTrace permission
@SuppressWarnings("removal" )
SecurityManager security = System.getSecurityManager();
if (security != null ) {
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
security.checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
}
// Get a snapshot of the list of all threads
Thread [] threads = getThreads();
StackTraceElement[][] traces = dumpThreads(threads);
Map<Thread , StackTraceElement[]> m = HashMap.newHashMap(threads.length);
for (int i = 0 ; i < threads.length; i++) {
Thread thread = threads[i];
StackTraceElement[] stackTrace = traces[i];
// BoundVirtualThread objects may be in list returned by the VM
if (!thread .isVirtual() && stackTrace != null ) {
m.put(threads[i], stackTrace);
}
// else terminated so we don't put it in the map
}
return m;
}
/** cache of subclass security audit results */
private static class Caches {
/** cache of subclass security audit results */
static final ClassValue<Boolean > subclassAudits =
new ClassValue<>() {
@Override
protected Boolean computeValue(Class <?> type) {
return auditSubclass(type);
}
};
}
/**
* Verifies that this ( possibly subclass ) instance can be constructed
* without violating security constraints : the subclass must not override
* security - sensitive non - final methods , or else the
* " enableContextClassLoaderOverride " RuntimePermission is checked .
*/
private static boolean isCCLOverridden(Class <?> cl) {
if (cl == Thread .class )
return false ;
return Caches.subclassAudits.get(cl);
}
/**
* Performs reflective checks on given subclass to verify that it doesn ' t
* override security - sensitive non - final methods . Returns true if the
* subclass overrides any of the methods , false otherwise .
*/
private static boolean auditSubclass(final Class <?> subcl) {
@SuppressWarnings("removal" )
Boolean result = AccessController.doPrivileged(
new PrivilegedAction<>() {
public Boolean run() {
for (Class <?> cl = subcl;
cl != Thread .class ;
cl = cl.getSuperclass())
{
try {
cl.getDeclaredMethod("getContextClassLoader" , new Class <?>[0 ]);
return Boolean .TRUE ;
} catch (NoSuchMethodException ex) {
}
try {
Class <?>[] params = {ClassLoader.class };
cl.getDeclaredMethod("setContextClassLoader" , params);
return Boolean .TRUE ;
} catch (NoSuchMethodException ex) {
}
}
return Boolean .FALSE ;
}
}
);
return result.booleanValue();
}
/**
* Return an array of all live threads .
*/
static Thread [] getAllThreads() {
Thread [] threads = getThreads();
return Stream.of(threads)
// BoundVirtualThread objects may be in list returned by the VM
.filter(Predicate.not(Thread ::isVirtual))
.toArray(Thread []::new );
}
private static native StackTraceElement[][] dumpThreads(Thread [] threads);
private static native Thread [] getThreads();
/**
* Returns the identifier of this Thread . The thread ID is a positive
* { @ code long } number generated when this thread was created .
* The thread ID is unique and remains unchanged during its lifetime .
*
* @ return this thread ' s ID
*
* @ deprecated This method is not final and may be overridden to return a
* value that is not the thread ID . Use { @ link # threadId ( ) } instead .
*
* @ since 1 . 5
*/
@Deprecated(since="19" )
public long getId() {
return threadId();
}
/**
* Returns the identifier of this Thread . The thread ID is a positive
* { @ code long } number generated when this thread was created .
* The thread ID is unique and remains unchanged during its lifetime .
*
* @ return this thread ' s ID
* @ since 19
*/
public final long threadId() {
return tid;
}
/**
* A thread state . A thread can be in one of the following states :
* < ul >
* < li > { @ link # NEW } < br >
* A thread that has not yet started is in this state .
* < / li >
* < li > { @ link # RUNNABLE } < br >
* A thread executing in the Java virtual machine is in this state .
* < / li >
* < li > { @ link # BLOCKED } < br >
* A thread that is blocked waiting for a monitor lock
* is in this state .
* < / li >
* < li > { @ link # WAITING } < br >
* A thread that is waiting indefinitely for another thread to
* perform a particular action is in this state .
* < / li >
* < li > { @ link # TIMED_WAITING } < br >
* A thread that is waiting for another thread to perform an action
* for up to a specified waiting time is in this state .
* < / li >
* < li > { @ link # TERMINATED } < br >
* A thread that has exited is in this state .
* < / li >
* < / ul >
*
* < p >
* A thread can be in only one state at a given point in time .
* These states are virtual machine states which do not reflect
* any operating system thread states .
*
* @ since 1 . 5
* @ see # getState
*/
public enum State {
/**
* Thread state for a thread which has not yet started .
*/
NEW ,
/**
* Thread state for a runnable thread . A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor .
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock .
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block / method or
* reenter a synchronized block / method after calling
* { @ link Object # wait ( ) Object . wait } .
*/
BLOCKED,
/**
* Thread state for a waiting thread .
* A thread is in the waiting state due to calling one of the
* following methods :
* < ul >
* < li > { @ link Object # wait ( ) Object . wait } with no timeout < / li >
* < li > { @ link # join ( ) Thread . join } with no timeout < / li >
* < li > { @ link LockSupport # park ( ) LockSupport . park } < / li >
* < / ul >
*
* < p > A thread in the waiting state is waiting for another thread to
* perform a particular action .
*
* For example , a thread that has called { @ code Object . wait ( ) }
* on an object is waiting for another thread to call
* { @ code Object . notify ( ) } or { @ code Object . notifyAll ( ) } on
* that object . A thread that has called { @ code Thread . join ( ) }
* is waiting for a specified thread to terminate .
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time .
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time :
* < ul >
* < li > { @ link # sleep Thread . sleep } < / li >
* < li > { @ link Object # wait ( long ) Object . wait } with timeout < / li >
* < li > { @ link # join ( long ) Thread . join } with timeout < / li >
* < li > { @ link LockSupport # parkNanos LockSupport . parkNanos } < / li >
* < li > { @ link LockSupport # parkUntil LockSupport . parkUntil } < / li >
* < / ul >
* /
TIMED_WAITING ,
/**
* Thread state for a terminated thread .
* The thread has completed execution .
*/
TERMINATED;
}
/**
* Returns the state of this thread .
* This method is designed for use in monitoring of the system state ,
* not for synchronization control .
*
* @ return this thread ' s state .
* @ since 1 . 5
*/
public State getState() {
return threadState();
}
/**
* Returns the state of this thread .
* This method can be used instead of getState as getState is not final and
* so can be overridden to run arbitrary code .
*/
State threadState() {
return jdk.internal.misc.VM.toThreadState(holder.threadStatus);
}
/**
* Returns true if the thread has terminated .
*/
boolean isTerminated() {
return threadState() == State.TERMINATED;
}
/**
* Interface for handlers invoked when a { @ code Thread } abruptly
* terminates due to an uncaught exception .
* < p > When a thread is about to terminate due to an uncaught exception
* the Java Virtual Machine will query the thread for its
* { @ code UncaughtExceptionHandler } using
* { @ link # getUncaughtExceptionHandler } and will invoke the handler ' s
* { @ code uncaughtException } method , passing the thread and the
* exception as arguments .
* If a thread has not had its { @ code UncaughtExceptionHandler }
* explicitly set , then its { @ code ThreadGroup } object acts as its
* { @ code UncaughtExceptionHandler } . If the { @ code ThreadGroup } object
* has no
* special requirements for dealing with the exception , it can forward
* the invocation to the { @ linkplain # getDefaultUncaughtExceptionHandler
* default uncaught exception handler } .
*
* @ see # setDefaultUncaughtExceptionHandler
* @ see # setUncaughtExceptionHandler
* @ see ThreadGroup # uncaughtException
* @ since 1 . 5
*/
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception .
* < p > Any exception thrown by this method will be ignored by the
* Java Virtual Machine .
* @ param t the thread
* @ param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
// null unless explicitly set
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
// null unless explicitly set
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
/**
* Set the default handler invoked when a thread abruptly terminates
* due to an uncaught exception , and no other handler has been defined
* for that thread .
*
* < p > Uncaught exception handling is controlled first by the thread , then
* by the thread ' s { @ link ThreadGroup } object and finally by the default
* uncaught exception handler . If the thread does not have an explicit
* uncaught exception handler set , and the thread ' s thread group
* ( including parent thread groups ) does not specialize its
* { @ code uncaughtException } method , then the default handler ' s
* { @ code uncaughtException } method will be invoked .
* < p > By setting the default uncaught exception handler , an application
* can change the way in which uncaught exceptions are handled ( such as
* logging to a specific device , or file ) for those threads that would
* already accept whatever & quot ; default & quot ; behavior the system
* provided .
*
* < p > Note that the default uncaught exception handler should not usually
* defer to the thread ' s { @ code ThreadGroup } object , as that could cause
* infinite recursion .
*
* @ param ueh the object to use as the default uncaught exception handler .
* If { @ code null } then there is no default handler .
*
* @ throws SecurityException if a security manager is present and it denies
* { @ link RuntimePermission } { @ code ( " setDefaultUncaughtExceptionHandler " ) }
*
* @ see # setUncaughtExceptionHandler
* @ see # getUncaughtExceptionHandler
* @ see ThreadGroup # uncaughtException
* @ since 1 . 5
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler ueh) {
@SuppressWarnings("removal" )
SecurityManager sm = System.getSecurityManager();
if (sm != null ) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler" ));
}
defaultUncaughtExceptionHandler = ueh;
}
/**
* Returns the default handler invoked when a thread abruptly terminates
* due to an uncaught exception . If the returned value is { @ code null } ,
* there is no default .
* @ since 1 . 5
* @ see # setDefaultUncaughtExceptionHandler
* @ return the default uncaught exception handler for all threads
*/
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
return defaultUncaughtExceptionHandler;
}
/**
* Returns the handler invoked when this thread abruptly terminates
* due to an uncaught exception . If this thread has not had an
* uncaught exception handler explicitly set then this thread ' s
* { @ code ThreadGroup } object is returned , unless this thread
* has terminated , in which case { @ code null } is returned .
* @ since 1 . 5
* @ return the uncaught exception handler for this thread
*/
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
if (isTerminated()) {
// uncaughtExceptionHandler may be set to null after thread terminates
return null ;
} else {
UncaughtExceptionHandler ueh = uncaughtExceptionHandler;
return (ueh != null ) ? ueh : getThreadGroup();
}
}
/**
* Set the handler invoked when this thread abruptly terminates
* due to an uncaught exception .
* < p > A thread can take full control of how it responds to uncaught
* exceptions by having its uncaught exception handler explicitly set .
* If no such handler is set then the thread ' s { @ code ThreadGroup }
* object acts as its handler .
* @ param ueh the object to use as this thread ' s uncaught exception
* handler . If { @ code null } then this thread has no explicit handler .
* @ throws SecurityException if the current thread is not allowed to
* modify this thread .
* @ see # setDefaultUncaughtExceptionHandler
* @ see ThreadGroup # uncaughtException
* @ since 1 . 5
*/
public void setUncaughtExceptionHandler(UncaughtExceptionHandler ueh) {
checkAccess();
uncaughtExceptionHandler(ueh);
}
void uncaughtExceptionHandler(UncaughtExceptionHandler ueh) {
uncaughtExceptionHandler = ueh;
}
/**
* Dispatch an uncaught exception to the handler . This method is
* called when a thread terminates with an exception .
*/
void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this , e);
}
/**
* Holder class for constants .
*/
@SuppressWarnings("removal" )
private static class Constants {
// Thread group for virtual threads.
static final ThreadGroup VTHREAD_GROUP;
// AccessControlContext that doesn't support any permissions.
@SuppressWarnings("removal" )
static final AccessControlContext NO_PERMISSIONS_ACC;
// Placeholder TCCL when thread locals not supported
static final ClassLoader NOT_SUPPORTED_CLASSLOADER;
static {
var getThreadGroup = new PrivilegedAction<ThreadGroup>() {
@Override
public ThreadGroup run() {
ThreadGroup parent = Thread .currentCarrierThread().getThreadGroup();
for (ThreadGroup p; (p = parent.getParent()) != null ; )
parent = p;
return parent;
}
};
@SuppressWarnings("removal" )
ThreadGroup root = AccessController.doPrivileged(getThreadGroup);
VTHREAD_GROUP = new ThreadGroup(root, "VirtualThreads" , MAX_PRIORITY, false );
NO_PERMISSIONS_ACC = new AccessControlContext(new ProtectionDomain[] {
new ProtectionDomain(null , null )
});
var createClassLoader = new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return new ClassLoader(null ) { };
}
};
@SuppressWarnings("removal" )
ClassLoader loader = AccessController.doPrivileged(createClassLoader);
NOT_SUPPORTED_CLASSLOADER = loader;
}
}
/**
* Returns the special ThreadGroup for virtual threads .
*/
static ThreadGroup virtualThreadGroup() {
return Constants.VTHREAD_GROUP;
}
// The following three initially uninitialized fields are exclusively
// managed by class java.util.concurrent.ThreadLocalRandom. These
// fields are used to build the high-performance PRNGs in the
// concurrent code.
/** The current seed for a ThreadLocalRandom */
long threadLocalRandomSeed;
/** Probe hash value; nonzero if threadLocalRandomSeed initialized */
int threadLocalRandomProbe;
/** Secondary seed isolated from public ThreadLocalRandom sequence */
int threadLocalRandomSecondarySeed;
/** The thread container that this thread is in */
private volatile ThreadContainer container; // @Stable candidate?
ThreadContainer threadContainer() {
return container;
}
void setThreadContainer(ThreadContainer container) {
// assert this.container == null;
this .container = container;
}
/** The top of this stack of stackable scopes owned by this thread */
private volatile StackableScope headStackableScopes;
StackableScope headStackableScopes() {
return headStackableScopes;
}
static void setHeadStackableScope(StackableScope scope) {
currentThread().headStackableScopes = scope;
}
/* Some private helper methods */
private native void setPriority0(int newPriority);
private native void interrupt0();
private static native void clearInterruptEvent();
private native void setNativeName(String name);
// The address of the next thread identifier, see ThreadIdentifiers.
private static native long getNextThreadIdOffset();
}
Messung V0.5 in Prozent C=94 H=90 G=91
¤ Dauer der Verarbeitung: 0.273 Sekunden
¤
*© Formatika GbR, Deutschland