package java.lang; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.security.AccessController; import java.security.AccessControlContext; import java.security.PrivilegedAction; import java.util.Map; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import sun.nio.ch.Interruptible; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.security.util.SecurityConstants; /** * A thread is a thread of execution in a program. The Java * Virtual Machine allows an application to have multiple threads of * execution running concurrently. *
* Every thread has a priority. Threads with higher priority are
* executed in preference to threads with lower priority. Each thread
* may or may not also be marked as a daemon. When code running in
* some thread creates a new Thread object, the new
* thread has its priority initially set equal to the priority of the
* creating thread, and is a daemon thread if and only if the
* creating thread is a daemon.
*
* When a Java Virtual Machine starts up, there is usually a single
* non-daemon thread (which typically calls the method named
* main of some designated class). The Java Virtual
* Machine continues to execute threads until either of the following
* occurs:
*
exit method of class Runtime has been
* called and the security manager has permitted the exit operation
* to take place.
* run method or by
* throwing an exception that propagates beyond the run
* method.
*
* There are two ways to create a new thread of execution. One is to
* declare a class to be a subclass of Thread. This
* subclass should override the run method of class
* Thread. An instance of the subclass can then be
* allocated and started. For example, a thread that computes primes
* larger than a stated value could be written as follows:
*
* class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
* * The following code would then create a thread and start it running: *
** PrimeThread p = new PrimeThread(143); * p.start(); *
* The other way to create a thread is to declare a class that
* implements the Runnable interface. That class then
* implements the run method. An instance of the class can
* then be allocated, passed as an argument when creating
* Thread, and started. The same example in this other
* style looks like the following:
*
* class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
* * The following code would then create a thread and start it running: *
** PrimeRun p = new PrimeRun(143); * new Thread(p).start(); *
* Every thread has a name for identification purposes. More than * one thread may have the same name. If a name is not specified when * a thread is created, a new name is generated for it. *
* Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. * * @see Runnable * @see Runtime#exit(int) * @see #run() * @see #stop() */ public class Thread implements Runnable { /** * 类加载的时候,调用本地的注册本地静态方法 */ private static native void registerNatives(); static { registerNatives(); } /** * 线程名称 */ private volatile String name; /** * 优先级 */ private int priority; /** * 是否是守护线程,true 是守护线程。如果是守护线程的话,是不能够阻止 JVM 的退出的,级别很低 */ private boolean daemon = false; /** * JVM 状态 */ private boolean stillborn = false; /** * 实际被执行的对象 */ private Runnable target; /** * 该线程的线程组 */ private ThreadGroup group; /** * 该线程的上下文类加载器 */ private ClassLoader contextClassLoader; /* The inherited AccessControlContext of this thread */ private AccessControlContext inheritedAccessControlContext; /** * 给线程自动生成名称所用 */ private static int threadInitNumber; /** * 同一时刻只会有一个线程修改 threadInitNumber 的值,线程安全 * * @return */ private static synchronized int nextThreadNum() { return threadInitNumber++; } /** * ThreadLocal 的 ThreadLocalMap 是线程的一个属性,所以在多线程环境下 threadLocals 是线程安全的 */ ThreadLocal.ThreadLocalMap threadLocals = null; /** * 当创建子线程时,子线程可以得到父线程的 inheritableThreadLocals */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; /** * 此线程请求的堆栈大小 */ private long stackSize; /* * JVM-private state that persists after native thread termination. */ private long nativeParkEventPointer; /** * 线程 ID */ private long tid; /** * 用于生成线程 ID */ private static long threadSeqNumber; /** * 线程状态 */ private volatile int threadStatus = 0; /** * 同一时刻只会有一个线程修改 threadSeqNumber 的值,线程安全 * * @return */ private static synchronized long nextThreadID() { return ++threadSeqNumber; } /** * 此对象不为null时说明线程进入了park(阻塞)状态,参见 LockSupport * * @see java.util.concurrent.locks.LockSupport */ volatile Object parkBlocker; /** * 线程中断回调标记,设置此标记后,可在线程被中断时调用标记对象的回调方法 */ private volatile Interruptible blocker; /** * 临时使用的锁,在设置/获取线程中断回调标记时使用 */ private final Object blockerLock = new Object(); /** * 为当前线程设置一个线程中断回调标记,以便在线程被中断时调用该标记的回调方法 */ void blockedOn(Interruptible b) { synchronized (blockerLock) { blocker = b; } } /** * 最低优先级 */ public final static int MIN_PRIORITY = 1; /** * 普通优先级,也是默认的 */ public final static int NORM_PRIORITY = 5; /** * 最高优先级 */ public final static int MAX_PRIORITY = 10; /** * 返回当前正在执行的线程对象的引用 * * @return 当前正在执行的线程 */ public static native Thread currentThread(); /** * 当前线程做出让步,放弃当前 cpu,让线程重新选择 cpu,避免线程过度使用 cpu * 让步不是不执行,也有可能重新选中自己 * 当前线程让出 cpu 时间片,重新抢占执行权 */ public static native void yield(); /** * 沉睡,锁不会释放,在 millis 毫秒之后会自己醒来 * 使线程进入 TIMED_WAITING 状态,millis毫秒后自己醒来(不释放锁) * * @param millis 睡眠时间 * @throws IllegalArgumentException 若 millis 为负数 * @throws InterruptedException if any thread has interrupted the current thread. The * interrupted status of the current thread is * cleared when this exception is thrown. */ public static native void sleep(long millis) throws InterruptedException; /** * 使线程进入TIMED_WAITING状态 * 至少等待millis毫秒,nanos是一个纳秒级的附加时间,用来微调millis参数(不释放锁) * * @param millis 睡眠时间 * @param nanos {@code 0-999999} 额外的纳秒睡眠时间 * @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 * interrupted status of the current thread is * cleared when this exception is thrown. */ public static void sleep(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"); } // 纳秒大于 0.5 毫秒,算一个毫秒 if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); } /** * Initializes a Thread with the current AccessControlContext. * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean) */ private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null, true); } /** * 初始化一个线程 * * @param g 代表线程组,线程组可以对组内的线程进行批量的操作,比如批量的打断 interrupt * @param target run()方法被调用的对象,也就是我们要运行的对象 * @param name 新线程的名称 * @param stackSize 可以设置堆栈的大小 * @param acc the AccessControlContext to inherit, or * AccessController.getContext() if null * @param inheritThreadLocals if {@code true}, inherit initial values for * inheritable thread-locals from the constructing thread */ private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { if (name == null) { throw new NullPointerException("name cannot be null"); } this.name = name; // 当前线程作为父线程 Thread parent = currentThread(); // 如果安全管理器不为空,从安全管理器中拿线程组 // 否则继承父线程的线程组 SecurityManager security = System.getSecurityManager(); if (g == null) { /* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager what to do. */ if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess(); /* * Do we have the required permissions? */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; // 子线程会继承父线程的守护属性 this.daemon = parent.isDaemon(); // 子线程继承父线程的优先级属性 this.priority = parent.getPriority(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext(); this.target = target; setPriority(priority); // 当父线程的 inheritableThreadLocals 的值不为空时 // 会把 inheritableThreadLocals 里面的值全部传递给子线程 if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; // 线程 id 自增 tid = nextThreadID(); } /** * 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(); } /** * Allocates a new {@code Thread} object. 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-"+}n, where n is an integer. */ public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, target, gname)}, where {@code gname} is a newly generated * name. Automatically generated names are of the form * {@code "Thread-"+}n, where n is an integer. * * @param target * the object whose {@code run} method is invoked when this thread * is started. If {@code null}, this classes {@code run} method does * nothing. */ // 名称的初始化 public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } /** * Creates a new Thread that inherits the given AccessControlContext. * This is not a public constructor. */ Thread(Runnable target, AccessControlContext acc) { init(null, target, "Thread-" + nextThreadNum(), 0, acc, false); } /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (group, target, gname)} ,where {@code gname} is a newly generated * name. Automatically generated names are of the form * {@code "Thread-"+}n, where n is an integer. * * @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 target * 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 */ public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, null, name)}. * * @param name * the name of the new thread */ public Thread(String name) { init(null, null, name, 0); } /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (group, null, name)}. * * @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 */ public Thread(ThreadGroup group, String name) { init(group, null, name, 0); } /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} * {@code (null, target, name)}. * * @param target * 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 */ public Thread(Runnable target, String name) { init(null, target, name, 0); } /** * Allocates a new {@code Thread} object so that it has {@code target} * as its run object, has the specified {@code name} as its name, * and belongs to the thread group referred to by {@code group}. * *
If there is a security manager, its * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess} * method is invoked with the ThreadGroup as its argument. * *
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. * *
The priority of the newly created thread is set equal to the * priority of the thread creating it, that is, the currently running * thread. The method {@linkplain #setPriority setPriority} may be * used to change the priority to a new value. * *
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. * * @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 target * 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. */ public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); } /** * Allocates a new {@code Thread} object so that it has {@code target} * 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 stack size. * *
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. The effect of the * {@code stackSize} parameter, if any, is highly platform dependent. * *
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 stackSize parameter * and the maximum recursion depth and concurrency level are * platform-dependent. On some platforms, the value of the * {@code stackSize} parameter may have no effect whatsoever. * *
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). * *
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. * *
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. * *
Implementation note: Java platform implementers are encouraged to * document their implementation's behavior with respect to the * {@code stackSize} parameter. * * * @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 target * 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 */ public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize); } /** * 该方法可以创建一个新的线程出来,返回的仍然是主线程 * 启动线程,线程状态从 NEW 进入 RUNNABLE * * @throws IllegalThreadStateException 若线程已经启动 * @see #run() * @see #stop() */ public synchronized void start() { // 如果没有初始化,抛异常 if (threadStatus != 0) throw new IllegalThreadStateException(); // 将当前线程加入到所在的线程组,记录为活跃线程 group.add(this); // started 是个标识符,我们在初始化一些东西的时候,经常这么写 boolean started = false; try { // 这里会创建一个新的线程,执行完成之后,新的线程已经在运行了,既 target 的内容已经在运行了 start0(); // 这里执行的还是主线程 started = true; } finally { try { // 如果失败,把线程从线程组中删除 if (!started) { group.threadStartFailed(this); } // 这里的 catch 捕捉也是值得我们学习的,我们在工作中 catch 时也应该多用 Throwable,少用 Exception // 比如对于异步线程抛出来的异常,Exception 是捕捉不住的,Throwable 却可以 } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } /** * 开启新线程使用的是 native 方法 */ private native void start0(); /** * 简单的运行,不会新起线程 * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */ @Override public void run() { if (target != null) { target.run(); } } /** * This method is called by the system to give a Thread * a chance to clean up before it actually exits. */ private void exit() { if (group != null) { group.threadTerminated(this); group = null; } /* Aggressively null out all reference fields: see bug 4006245 */ target = null; /* Speed the release of some of these resources */ threadLocals = null; inheritableThreadLocals = null; inheritedAccessControlContext = null; blocker = null; uncaughtExceptionHandler = null; } /** * Forces the thread to stop executing. *
* If there is a security manager installed, its checkAccess
* method is called with this
* as its argument. This may result in a
* SecurityException being raised (in the current thread).
*
* If this thread is different from the current thread (that is, the current
* thread is trying to stop a thread other than itself), the
* security manager's checkPermission method (with a
* RuntimePermission("stopThread") argument) is called in
* addition.
* Again, this may result in throwing a
* SecurityException (in the current thread).
*
* The thread represented by this thread is forced to stop whatever
* it is doing abnormally and to throw a newly created
* ThreadDeath object as an exception.
*
* It is permitted to stop a thread that has not yet been started. * If the thread is eventually started, it immediately terminates. *
* An application should not normally try to catch
* ThreadDeath unless it must do some extraordinary
* cleanup operation (note that the throwing of
* ThreadDeath causes finally clauses of
* try statements to be executed before the thread
* officially dies). If a catch clause catches a
* ThreadDeath object, it is important to rethrow the
* object so that the thread actually dies.
*
* The top-level error handler that reacts to otherwise uncaught
* exceptions does not print out a message or otherwise notify the
* application if the uncaught exception is an instance of
* ThreadDeath.
*
* @exception SecurityException if the current thread cannot
* modify this thread.
* @see #interrupt()
* @see #checkAccess()
* @see #run()
* @see #start()
* @see ThreadDeath
* @see ThreadGroup#uncaughtException(Thread,Throwable)
* @see SecurityManager#checkAccess(Thread)
* @see SecurityManager#checkPermission
* @deprecated This method is inherently unsafe. Stopping a thread with
* Thread.stop causes it to unlock all of the monitors that it
* has locked (as a natural consequence of the unchecked
* ThreadDeath exception propagating up the stack). If
* any of the objects previously protected by these monitors were in
* an inconsistent state, the damaged objects become visible to
* other threads, potentially resulting in arbitrary behavior. Many
* uses of 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 interrupt method should be used to
* interrupt the wait.
* For more information, see
* Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
*/
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if (this != Thread.currentThread()) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW", it can't change to
// not-NEW because we hold the lock.
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
}
// The VM can handle all thread states
stop0(new ThreadDeath());
}
/**
* Throws {@code UnsupportedOperationException}.
*
* @param obj ignored
*
* @deprecated This method was originally designed to force a thread to stop
* and throw a given {@code Throwable} as an exception. It was
* inherently unsafe (see {@link #stop()} for details), and furthermore
* could be used to generate exceptions that the target thread was
* not prepared to handle.
* For more information, see
* Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
*/
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
/**
* 中断线程(只是给线程预设一个标记,不是立即让线程停下来)
*
* @throws SecurityException 若当前线程无法修改
*/
public void interrupt() {
// 如果由别的线程对当前线程发起中断
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
// 如果存在线程中断回调标记
if (b != null) {
// 设置中断标记
interrupt0();
b.interrupt(this);
return;
}
}
interrupt0();
}
/**
* Tests whether the current thread has been interrupted. The
* interrupted status 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).
*
*
A thread interruption ignored because a thread was not alive
* at the time of the interrupt will be reflected by this method
* returning false.
*
* @return true if the current thread has been interrupted;
* false otherwise.
* @see #isInterrupted()
* @revised 6.0
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* Tests whether this thread has been interrupted. The interrupted
* status of the thread is unaffected by this method.
*
*
A thread interruption ignored because a thread was not alive
* at the time of the interrupt will be reflected by this method
* returning false.
*
* @return true if this thread has been interrupted;
* false otherwise.
* @see #interrupted()
* @revised 6.0
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* Tests if some Thread has been interrupted. The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/
private native boolean isInterrupted(boolean ClearInterrupted);
/**
* Throws {@link NoSuchMethodError}.
*
* @deprecated This method was originally designed to destroy this
* thread without any cleanup. Any monitors it held would have
* remained locked. However, the method was never implemented.
* If if were to be implemented, it would be deadlock-prone in
* much the manner of {@link #suspend}. If the target thread held
* a lock protecting a critical system resource when it was
* destroyed, no thread could ever access this resource again.
* If another thread ever attempted to lock this resource, deadlock
* would result. Such deadlocks typically manifest themselves as
* "frozen" processes. For more information, see
*
* Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
* @throws NoSuchMethodError always
*/
@Deprecated
public void destroy() {
throw new NoSuchMethodError();
}
/**
* 判断当前线程是否仍然存活(没有到达 TERMINATED 状态)
*
* @return 若存活返回 true
*/
public final native boolean isAlive();
/**
* Suspends this thread.
*
* First, the checkAccess method of this thread is called
* with no arguments. This may result in throwing a
* SecurityException (in the current thread).
*
* If the thread is alive, it is suspended and makes no further
* progress unless and until it is resumed.
*
* @exception SecurityException if the current thread cannot modify
* this thread.
* @see #checkAccess
* @deprecated This method has been deprecated, as it is
* inherently deadlock-prone. If the target thread holds a lock on the
* monitor protecting a critical system resource when it is suspended, no
* thread can access this resource until the target thread is resumed. If
* the thread that would resume the target thread attempts to lock this
* monitor prior to calling resume, deadlock results. Such
* deadlocks typically manifest themselves as "frozen" processes.
* For more information, see
* Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
/**
* Resumes a suspended thread.
*
* First, the checkAccess method of this thread is called
* with no arguments. This may result in throwing a
* SecurityException (in the current thread).
*
* If the thread is alive but suspended, it is resumed and is * permitted to make progress in its execution. * * @exception SecurityException if the current thread cannot modify this * thread. * @see #checkAccess * @see #suspend() * @deprecated This method exists solely for use with {@link #suspend}, * which has been deprecated because it is deadlock-prone. * For more information, see * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ @Deprecated public final void resume() { checkAccess(); resume0(); } /** * 设置线程优先级 * * @param newPriority priority to set this thread to * @throws IllegalArgumentException 如果优先级不在 MIN_PRIORITY 到 MAX_PRIORITY 范围内 * @throws SecurityException 若不能修改当前线程 * @see #getPriority * @see #checkAccess() * @see #getThreadGroup() * @see #MAX_PRIORITY * @see #MIN_PRIORITY * @see ThreadGroup#getMaxPriority() */ public final void setPriority(int newPriority) { ThreadGroup g; checkAccess(); if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); } } /** * 返回该线程的优先级 * * @return 该线程的优先级 * @see #setPriority */ public final int getPriority() { return priority; } /** * 设置线程名称 * * @param name 线程名称 * @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 (threadStatus != 0) { setNativeName(name); } } /** * 返回该线程的名字 * * @return 该线程的名字 * @see #setName(String) */ public final String getName() { return name; } /** * 返回此线程所属的线程组 * 若该线程已经死亡(停止),则返回null * * @return 此线程所属的线程组 */ public final ThreadGroup getThreadGroup() { return group; } /** * 递归获取当前线程所在线程组的所有活跃线程数量(可能与实际数量有出入,因为线程数量动态变化),建议仅用作监视目的 * * @return 当前线程所在线程组的所有活跃线程数量 */ public static int activeCount() { return currentThread().getThreadGroup().activeCount(); } /** * 递归获取当前线程所在线程组的所有线程(可能与实际状态有出入,因为线程数量动态变化),建议仅用作监视目的 * * @param tarray 当前线程的线程组 * @return 线程组的所有数量数量 * @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); } /** * Counts the number of stack frames in this thread. The thread must * be suspended. * * @return the number of stack frames in this thread. * @exception IllegalThreadStateException if this thread is not * suspended. * @deprecated The definition of this call depends on {@link #suspend}, * which is deprecated. Further, the results of this call * were never well-defined. */ @Deprecated public native int countStackFrames(); /** * 使该方法的调用者所在的线程进入 WAITING 或 TIMED_WAITING 状态,直到当前线程死亡,或者等待超时之后,再去执行上述调用者线程 * * @param millis 等待时间 * @throws IllegalArgumentException if the value of {@code millis} is negative * @throws InterruptedException if any thread has interrupted the current thread. The * interrupted status of the current thread is * cleared when this exception is thrown. */ public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { // 其他线程好了之后,当前线程的状态是 TERMINATED,isAlive 返回 false // NEW false // RUNNABLE true while (isAlive()) { // 等待其他线程,一直等待 wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } // 等待一定的时间,如果在 delay 时间内,等待的线程仍没有结束,放弃等待 wait(delay); now = System.currentTimeMillis() - base; } } } /** * 使该方法的调用者所在的线程进入 WAITING 或 TIMED_WAITING 状态,直到当前线程死亡,或者等待超时之后,再去执行上述调用者线程 * 注:millis的单位是毫秒,且为非负数;nanos的单位是纳秒,其取值范围在1毫秒之内,与millis共同组成超时限制 * * @param millis 等待时间 * @param nanos {@code 0-999999} 额外等待时间 * @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 * interrupted status of the current thread is * cleared when this exception is thrown. */ public final synchronized void join(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } // 纳秒的取值在1毫秒之内 if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis); } /** * 使该方法的调用者所在的线程进入 WAITING 状态,直到当前线程死亡之后,再去执行上述调用者线程 * * @throws InterruptedException if any thread has interrupted the current thread. The * interrupted status of the current thread is * cleared when this exception is thrown. */ public final void join() throws InterruptedException { join(0); } /** * 打印当前线程的异常栈信息,此方法仅用于调试 * * @see Throwable#printStackTrace() */ public static void dumpStack() { new Exception("Stack trace").printStackTrace(); } /** * 设置当前线程为守护线程/非守护线程 * 线程开始之前此方法必须被调用 * * @param on 若为 true,则设置为守护线程 * @throws IllegalThreadStateException if this thread is {@linkplain #isAlive alive} * @throws SecurityException if {@link #checkAccess} determines that the current * thread cannot modify this thread */ public final void setDaemon(boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; } /** * 判断该线程是否为守护线程 * * @return 返回true代表当前线程是守护线程 * @see #setDaemon(boolean) */ public final boolean isDaemon() { return daemon; } /** * Determines if the currently running thread has permission to * modify this thread. *
* If there is a security manager, its 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
* uncaughtException method, then the default handler's
* uncaughtException method will be invoked.
* 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 "default" behavior the system
* provided.
*
* Note that the default uncaught exception handler should not usually
* defer to the thread's ThreadGroup object, as that could cause
* infinite recursion.
*
* @param eh the object to use as the default uncaught exception handler.
* If null then there is no default handler.
*
* @throws SecurityException if a security manager is present and it
* denies {@link RuntimePermission}
* ("setDefaultUncaughtExceptionHandler")
*
* @see #setUncaughtExceptionHandler
* @see #getUncaughtExceptionHandler
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
/**
* Returns the default handler invoked when a thread abruptly terminates
* due to an uncaught exception. If the returned value is 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
* ThreadGroup object is returned, unless this thread
* has terminated, in which case null is returned.
* @since 1.5
* @return the uncaught exception handler for this thread
*/
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
/**
* Set the handler invoked when this thread abruptly terminates
* due to an uncaught exception.
* 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 ThreadGroup
* object acts as its handler.
* @param eh the object to use as this thread's uncaught exception
* handler. If 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 eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
/**
* 当前线程内出现未捕获异常时,JVM 会调用此方法
*/
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
/**
* Removes from the specified map any keys that have been enqueued
* on the specified reference queue.
*/
static void processQueue(ReferenceQueuecheckAccess method
* is called with this thread as its argument. This may result in
* throwing a SecurityException.
*
* @exception SecurityException if the current thread is not allowed to
* access this thread.
* @see SecurityManager#checkAccess(Thread)
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
/**
* 返回该线程的字符串表示形式,包括线程名称,优先级和线程组
*
* @return 该线程的字符串表示
*/
public String toString() {
ThreadGroup group = getThreadGroup();
if (group != null) {
return "Thread[" + getName() + "," + getPriority() + "," +
group.getName() + "]";
} else {
return "Thread[" + getName() + "," + getPriority() + "," +
"" + "]";
}
}
/**
* 获取当前线程上下文类加载器
*
* @return the context ClassLoader for this Thread, or {@code null}
* indicating the system class loader (or, failing that, the
* bootstrap class loader)
* @throws SecurityException 如果当前线程无法获取上下文类加载器
*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
/**
* 设置线程上下文类加载器
*
* @param cl the context ClassLoader for this Thread, or null indicating the
* system class loader (or, failing that, the bootstrap class loader)
* @throws SecurityException 如果当前线程无法设置上下文类加载器
*/
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
/**
* 判断是否只有当前线程持有 obj 锁
*
* @param obj the object on which to test lock ownership
* @throws NullPointerException 若 obj 为 null
* @return 若只有当前线程持有 obj 锁,则返回 true
* @since 1.4
*/
public static native boolean holdsLock(Object obj);
/**
* 空栈帧
*/
private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
/**
* 获取当前线程中的栈帧
*
* @return StackTraceElement 数组,每一个元素代表一个栈帧
* @throws SecurityException if a security manager exists and its
* checkPermission method doesn't allow
* getting the stack trace of thread.
* @see SecurityManager#checkPermission
* @see RuntimePermission
* @see Throwable#getStackTrace
*/
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
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[][] stackTraceArray = dumpThreads(new Thread[] {this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}
/**
* 获取当前 JVM 中所有活跃线程的栈帧
*
* @throws SecurityException if a security manager exists and its
* checkPermission method doesn't allow
* getting the stack trace of thread.
* @see #getStackTrace
* @see SecurityManager#checkPermission
* @see RuntimePermission
* @see Throwable#getStackTrace
*/
public static Map