/* * 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.
*/
/** * A <i>thread</i> is a thread of execution in a program. The Java * virtual machine allows an application to have multiple threads of * execution 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 to terminate. * * <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. * Platform threads will usually have a large stack and other resources that are * 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}. * * <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 virtual thread is not aware of the underlying carrier 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 * the parent thread values at the time that the child {@code Thread} 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
*/ publicclassThreadimplements Runnable { /* Make sure registerNatives is the first thing <clinit> does. */ privatestaticnativevoid registerNatives(); static {
registerNatives();
}
/* Reserved for exclusive use by the JVM, maybe move to FieldHolder */ privatelong eetop;
// thread id privatefinallong tid;
// thread name privatevolatile String name;
// interrupt status (read/written by VM) volatileboolean interrupted;
// 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. privatestaticclass FieldHolder { final ThreadGroup group; final Runnable task; finallong stackSize; volatileint priority; volatileboolean daemon; volatileint threadStatus;
/* * 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. privatestaticfinal Object NEW_THREAD_BINDINGS = Thread.class;
/** * Search the stack for the most recent scoped-value bindings.
*/
@IntrinsicCandidate staticnative 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
*/ privatevolatile 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
*/ staticvoid blockedOn(Interruptible b) { Thread me = Thread.currentThread(); synchronized (me.interruptLock) {
me.nioBlocker = b;
}
}
/** * The minimum priority that a thread can have.
*/ publicstaticfinalint MIN_PRIORITY = 1;
/** * The default priority that is assigned to a thread.
*/ publicstaticfinalint NORM_PRIORITY = 5;
/** * The maximum priority that a thread can have.
*/ publicstaticfinalint 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 staticnativeThread currentCarrierThread();
/** * Returns the Thread object for the current thread. * @return the current thread
*/
@IntrinsicCandidate publicstaticnativeThread currentThread();
/** * Sets the Thread object to be returned by Thread.currentThread().
*/
@IntrinsicCandidate nativevoid setCurrentThread(Threadthread);
/** * 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.
*/ publicstaticvoid yield() { if (currentThread() instanceof VirtualThread vthread) {
vthread.tryYield();
} else {
yield0();
}
}
privatestaticnativevoid 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 has interrupted the current thread. The * <i>interrupted status</i> of the current thread is * cleared when this exception is thrown.
*/ publicstaticvoid sleep(long millis) throws InterruptedException { if (millis < 0) { thrownew IllegalArgumentException("timeout value is negative");
}
if (currentThread() instanceof VirtualThread vthread) { long nanos = MILLISECONDS.toNanos(millis);
vthread.sleepNanos(nanos); return;
}
/** * Causes the currently executing thread to sleep (temporarily cease * 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} * * @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.
*/ publicstaticvoid sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { thrownew IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) { thrownew 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;
}
/** * 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
*/ publicstaticvoid 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 += 1L;
}
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 publicstaticvoid onSpinWait() {}
/** * Characteristic value signifying that the thread cannot set values for its * copy of {@link ThreadLocal thread-locals}. * See Thread initialization.
*/ staticfinalint NO_THREAD_LOCALS = 1 << 1;
/** * Characteristic value signifying that initial values for {@link * InheritableThreadLocal inheritable-thread-locals} are not inherited from * the constructing thread. * See Thread initialization.
*/ staticfinalint 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.
*/ privatestaticclass ThreadIdentifiers { privatestaticfinal Unsafe U; privatestaticfinallong NEXT_TID_OFFSET; static {
U = Unsafe.getUnsafe();
NEXT_TID_OFFSET = Thread.getNextThreadIdOffset();
} staticlong next() { return U.getAndAddLong(null, NEXT_TID_OFFSET, 1);
}
}
/** * Returns the context class loader to inherit from the parent thread. * See Thread initialization.
*/ privatestatic 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 * @param stackSize the desired stack size for the new thread, or * 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) {
if (attached) { if (g == null) { thrownew 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();
}
// default to current thread's group 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 priority = Math.min(parent.getPriority(), g.getMaxPriority()); this.holder = new FieldHolder(g, task, stackSize, priority, parent.isDaemon());
}
// 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;
} elseif ((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;
}
} elseif (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;
} elseif ((characteristics & NO_INHERIT_THREAD_LOCALS) == 0) { Thread parent = currentThread();
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 (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 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) publicstatic Builder.OfPlatform ofPlatform() { returnnew 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(); * } * * @return A builder for creating {@code Thread} or {@code ThreadFactory} objects. * @throws UnsupportedOperationException if preview features are not enabled * @since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) publicstatic Builder.OfVirtual ofVirtual() {
PreviewFeatures.ensureEnabled(); returnnew 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 {
/** * Sets the thread name. * @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 seeded with the current value of the counter. The {@code * 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. * * <p> The initial values of {@code InheritableThreadLocal}s are never inherited * 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);
/** * 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 threads</a>) * * @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
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
sealed interface OfPlatform extends Builder
permits ThreadBuilders.PlatformThreadBuilder {
/** * 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. * * @see Thread#ofVirtual() * @since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS)
sealed interface OfVirtual extends Builder
permits ThreadBuilders.VirtualThreadBuilder {
/** * Throws CloneNotSupportedException as a Thread can not be meaningfully * cloned. Construct a new Thread instead. * * @throws CloneNotSupportedException * always
*/
@Override protected Object clone() throws CloneNotSupportedException { thrownew CloneNotSupportedException();
}
/** * Helper class for auto-numbering platform threads. The numbers start at * 0 and are separate from the thread identifier for historical reasons.
*/ privatestaticclass ThreadNumbering { privatestaticfinal Unsafe U; privatestaticfinal Object NEXT_BASE; privatestaticfinallong NEXT_OFFSET; static {
U = Unsafe.getUnsafe(); try {
Field nextField = ThreadNumbering.class.getDeclaredField("next");
NEXT_BASE = U.staticFieldBase(nextField);
NEXT_OFFSET = U.staticFieldOffset(nextField);
} catch (NoSuchFieldException e) { thrownew ExceptionInInitializerError(e);
}
} privatestaticvolatileint next; staticint 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.
*/ privatestatic String checkName(String name) { if (name == null) thrownew 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>
*/ publicThread() { 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>
*/ publicThread(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>
*/ publicThread(ThreadGroup group, Runnable task) { 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>
*/ publicThread(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>
*/ publicThread(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>
*/ publicThread(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>
*/ publicThread(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: * <pre>{@code Thread.ofPlatform().group(group).name(name).stackSize(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>
*/ publicThread(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 inheritThreadLocals} * 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 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 * * @param inheritInheritableThreadLocals * 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>
*/ publicThread(ThreadGroup group, Runnable task, String name, long stackSize, boolean inheritInheritableThreadLocals) { this(group, checkName(name),
(inheritInheritableThreadLocals ? 0 : NO_INHERIT_THREAD_LOCALS),
task, stackSize, null);
}
/** * Creates a virtual thread to execute a task and schedules it to execute. * * <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="#inheritance">Inheritance when creating threads</a> * @since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) publicstaticThread startVirtualThread(Runnable task) {
Objects.requireNonNull(task);
PreviewFeatures.ensureEnabled(); varthread = ThreadBuilders.newVirtualThread(null, null, 0, task); thread.start(); returnthread;
}
/** * 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 * * @since 19
*/
@PreviewFeature(feature = PreviewFeature.Feature.VIRTUAL_THREADS) publicfinalboolean isVirtual() { return (thisinstanceof 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
*/ publicvoid start() { synchronized (this) {
--> --------------------
--> maximum size reached
--> --------------------
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.33Angebot
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.