天天看点

Thread类【JDK源码分析】

Thread类【JDK源码分析】

  • ​​前言​​
  • ​​推荐​​
  • ​​说明​​
  • ​​Thread类​​
  • ​​基本信息​​
  • ​​嵌套类摘要​​
  • ​​字段摘要​​
  • ​​方法摘要​​
  • ​​currentThread​​
  • ​​yield​​
  • ​​sleep​​
  • ​​sleep​​
  • ​​start​​
  • ​​start0​​
  • ​​run​​
  • ​​Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?翻译​​
  • ​​stop​​
  • ​​interrupt​​
  • ​​interrupted​​
  • ​​isInterrupted​​
  • ​​destroy​​
  • ​​suspend​​
  • ​​resume​​
  • ​​join​​
  • ​​join​​
  • ​​join​​
  • ​​GetterSetter​​
  • ​​测试​​
  • ​​附:Thread源码​​
  • ​​总结​​
  • ​​最后​​

前言

2022/10/25

路漫漫其修远兮,吾将上下而求索

本文是根据jdk学习所做笔记

仅供学习交流使用,转载注明出处

推荐

JDK API 1.6 中文版

说明

以下内容是结合很多资料进行编写的

源码为jdk1.8的

斜体样式 为自己的思考

下划线为自己所画的重点

Thread类

基本信息

java.lang

类 Thread

java.lang.Object

继承者 java.lang.Thread

所有已实现的接口:

Runnable

public class Thread

extends Object

implements Runnable

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。

当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:

  • 调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。
  • 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。

创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:

class PrimeThread extends Thread {
     long minPrime;
     PrimeThread(long minPrime) {
         this.minPrime = minPrime;
     }
 
     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }      

然后,下列代码会创建并启动一个线程:

PrimeThread p = new PrimeThread(143);
 p.start();      

创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:

class PrimeRun implements Runnable {
     long minPrime;
     PrimeRun(long minPrime) {
         this.minPrime = minPrime;
     }
 
     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }      

然后,下列代码会创建并启动一个线程:

PrimeRun p = new PrimeRun(143);
 new Thread(p).start();      

每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。

从以下版本开始:

JDK1.0

另请参见:

Runnable, Runtime.exit(int), run(), stop()

嵌套类摘要

static class

Thread.State

线程状态。

java.lang

枚举 Thread.State

java.lang.Object

继承者 java.lang.Enum<Thread.State>

继承者 java.lang.Thread.State

所有已实现的接口:

Serializable, Comparable<Thread.State>

正在封闭类:

Thread

public static enum Thread.Stateextends Enum<Thread.State>线程状态。线程可以处于下列状态之一:

NEW

至今尚未启动的线程处于这种状态。

RUNNABLE

正在 Java 虚拟机中执行的线程处于这种状态。

BLOCKED

受阻塞并等待某个监视器锁的线程处于这种状态。

WAITING

无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。

TIMED_WAITING

等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。

TERMINATED

已退出的线程处于这种状态。

在给定时间点上,一个线程只能处于一种状态。这些状态是虚拟机状态,它们并没有反映所有操作系统线程状态。

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

    /**
     * Returns the state of this thread.
     * This method is designed for use in monitoring of the system state,
     * not for synchronization control.
     *
     * @return this thread's state.
     * @since 1.5
     */
    public State getState() {
        // get current thread state
        return sun.misc.VM.toThreadState(threadStatus);
    }      

static interface

Thread.UncaughtExceptionHandler

当 Thread 因未捕获的异常而突然终止时,调用处理程序的接口。

java.lang

接口 Thread.UncaughtExceptionHandler

所有已知实现类:

ThreadGroup

正在封闭类:

Thread

public static interface Thread.UncaughtExceptionHandler当 Thread 因未捕获的异常而突然终止时,调用处理程序的接口。

当某一线程因未捕获的异常而即将终止时,Java 虚拟机将使用 Thread.getUncaughtExceptionHandler() 查询该线程以获得其 UncaughtExceptionHandler 的线程,并调用处理程序的 uncaughtException 方法,将线程和异常作为参数传递。如果某一线程没有明确设置其 UncaughtExceptionHandler,则将它的 ThreadGroup 对象作为其 UncaughtExceptionHandler。如果 ThreadGroup 对象对处理异常没有什么特殊要求,那么它可以将调用转发给默认的未捕获异常处理程序。

从以下版本开始:

1.5

另请参见:

Thread.setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler), Thread.setUncaughtExceptionHandler

(java.lang.Thread.UncaughtExceptionHandler), ThreadGroup.uncaughtException(java.lang.Thread, java.lang.Throwable)

// Added in JSR-166

    /**
     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
     * terminates due to an uncaught exception.
     * <p>When a thread is about to terminate due to an uncaught exception
     * the Java Virtual Machine will query the thread for its
     * <tt>UncaughtExceptionHandler</tt> using
     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
     * <tt>uncaughtException</tt> method, passing the thread and the
     * exception as arguments.
     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
     * has no
     * special requirements for dealing with the exception, it can forward
     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
     * default uncaught exception handler}.
     *
     * @see #setDefaultUncaughtExceptionHandler
     * @see #setUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * Method invoked when the given thread terminates due to the
         * given uncaught exception.
         * <p>Any exception thrown by this method will be ignored by the
         * Java Virtual Machine.
         * @param t the thread
         * @param e the exception
         */
        void uncaughtException(Thread t, Throwable e);
    }      

字段摘要

static int MAX_PRIORITY

线程可以具有的最高优先级。

static int MIN_PRIORITY

线程可以具有的最低优先级。

static int NORM_PRIORITY

分配给线程的默认优先级。

/**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;      

方法摘要

currentThread

public static Thread currentThread()

返回对当前正在执行的线程对象的引用。

返回:

当前执行的线程。

/**
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static native Thread currentThread();      

yield

public static void yield()

暂停当前正在执行的线程对象,并执行其他线程。

/**
     * A hint to the scheduler that the current thread is willing to yield
     * its current use of a processor. The scheduler is free to ignore this
     * hint.
     *
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
    public static native void yield();      

sleep

public static void sleep(long millis)

throws InterruptedException

在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。

参数:

millis - 以毫秒为单位的休眠时间。

抛出:

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

另请参见:

Object.notify()

/**
     * 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.
     */
    public static native void sleep(long millis) throws InterruptedException;      

sleep

public static void sleep(long millis,

int nanos)

throws InterruptedException

在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。

参数:

millis - 以毫秒为单位的休眠时间。

nanos - 要休眠的另外 0-999999 纳秒。

抛出:

IllegalArgumentException - 如果 millis 值为负或 nanos 值不在 0-999999 范围内。

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

另请参见:

Object.notify()

/**
     * 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.
     */
    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");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }      

start

public void start()

使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。

多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。

抛出:

IllegalThreadStateException - 如果线程已经启动。

另请参见:

run(), stop()

/**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }      

start0

native方法

java不是真正意义上的创建线程

private native void start0();      

run

public void run()

如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

Thread 的子类应该重写该方法。

指定者:

接口 Runnable 中的 run

另请参见:

start(), stop(), Thread(ThreadGroup, Runnable, String)

/**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }      

Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?翻译

​​Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?翻译​​

stop

@Deprecated

public final void stop()已过时。

该方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器(作为沿堆栈向上传播的未检查 ThreadDeath 异常的一个自然后果)。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为。stop 的许多使用都应由只修改某些变量以指示目标线程应该停止运行的代码来取代。目标线程应定期检查该变量,并且如果该变量指示它要停止运行,则从其运行方法依次返回。如果目标线程等待很长时间(例如基于一个条件变量),则应使用 interrupt 方法来中断该等待。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。

强迫线程停止执行。

如果安装了安全管理器,则以 this 作为其参数调用 checkAccess 方法。这可能引发 SecurityException(在当前线程中)。

如果该线程不同于当前线程(即当前线程试图终止除它本身以外的某一线程),则安全管理器的 checkPermission 方法(带有 RuntimePermission(“stopThread”) 参数)也会被调用。这会再次抛出 SecurityException(在当前线程中)。

无论该线程在做些什么,它所代表的线程都被迫异常停止,并抛出一个新创建的 ThreadDeath 对象,作为异常。

停止一个尚未启动的线程是允许的。如果最后启动了该线程,它会立即终止。

应用程序通常不应试图捕获 ThreadDeath,除非它必须执行某些异常的清除操作(注意,抛出 ThreadDeath 将导致 try 语句的 finally 子句在线程正式终止前执行)。如果 catch 子句捕获了一个 ThreadDeath 对象,则重新抛出该对象很重要,因为这样该线程才会真正终止。

对其他未捕获的异常作出反应的顶级错误处理程序不会打印输出消息,或者另外通知应用程序未捕获到的异常是否为 ThreadDeath 的一个实例。

抛出:

SecurityException - 如果当前线程不能修改该线程。

另请参见:

interrupt(), checkAccess(), run(), start(), ThreadDeath, ThreadGroup.uncaughtException(Thread,Throwable), SecurityManager.checkAccess(Thread), SecurityManager.checkPermission(java.security.Permission)

interrupt

public void interrupt()中断线程。

如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。

如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。

如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。

如果该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法一样。

如果以前的条件都没有保存,则该线程的中断状态将被设置。

中断一个不处于活动状态的线程不需要任何作用。

抛出:

SecurityException - 如果当前线程无法修改该线程

/**
     * Interrupts this thread.
     *
     * <p> Unless the current thread is interrupting itself, which is
     * always permitted, the {@link #checkAccess() checkAccess} method
     * of this thread is invoked, which may cause a {@link
     * SecurityException} to be thrown.
     *
     * <p> If this thread is blocked in an invocation of the {@link
     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
     * class, or of the {@link #join()}, {@link #join(long)}, {@link
     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
     * methods of this class, then its interrupt status will be cleared and it
     * will receive an {@link InterruptedException}.
     *
     * <p> If this thread is blocked in an I/O operation upon an {@link
     * java.nio.channels.InterruptibleChannel InterruptibleChannel}
     * then the channel will be closed, the thread's interrupt
     * status will be set, and the thread will receive a {@link
     * java.nio.channels.ClosedByInterruptException}.
     *
     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
     * then the thread's interrupt status will be set and it will return
     * immediately from the selection operation, possibly with a non-zero
     * value, just as if the selector's {@link
     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
     *
     * <p> If none of the previous conditions hold then this thread's interrupt
     * status will be set. </p>
     *
     * <p> Interrupting a thread that is not alive need not have any effect.
     *
     * @throws  SecurityException
     *          if the current thread cannot modify this thread
     *
     * @revised 6.0
     * @spec JSR-51
     */
    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }      

interrupted

public static boolean interrupted()测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。

线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。

返回:

如果当前线程已经中断,则返回 true;否则返回 false。

另请参见:

isInterrupted()

isInterrupted

public boolean isInterrupted()测试线程是否已经中断。线程的中断状态 不受该方法的影响。

线程中断被忽略,因为在中断时不处于活动状态的线程将由此返回 false 的方法反映出来。

返回:

如果该线程已经中断,则返回 true;否则返回 false。

另请参见:

interrupted()

destroy

@Deprecated

public void destroy()已过时。 该方法最初用于破坏该线程,但不作任何清除。它所保持的任何监视器都会保持锁定状态。不过,该方法决不会被实现。即使要实现,它也极有可能以 suspend() 方式被死锁。如果目标线程被破坏时保持一个保护关键系统资源的锁,则任何线程在任何时候都无法再次访问该资源。如果另一个线程曾试图锁定该资源,则会出现死锁。这类死锁通常会证明它们自己是“冻结”的进程。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。

抛出 NoSuchMethodError。

抛出:

NoSuchMethodError - 始终

isAlive

public final boolean isAlive()测试线程是否处于活动状态。如果线程已经启动且尚未终止,则为活动状态。

返回:

如果该线程处于活动状态,则返回 true;否则返回 false。

suspend

@Deprecated

public final void suspend()已过时。 该方法已经遭到反对,因为它具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源。如果重新开始目标线程的线程想在调用 resume 之前锁定该监视器,则会发生死锁。这类死锁通常会证明自己是“冻结”的进程。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。

挂起线程。

首先,调用线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。

如果线程处于活动状态则被挂起,且不再有进一步的活动,除非重新开始。

抛出:

SecurityException - 如果当前线程不能修改该线程。

另请参见:

checkAccess()

resume

@Deprecated

public final void resume()已过时。 该方法只与 suspend() 一起使用,但 suspend() 已经遭到反对,因为它具有死锁倾向。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?。

重新开始挂起的进程。

首先,调用线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。

如果线程处于活动状态但被挂起,则它会在执行过程中重新开始并允许继续活动。

抛出:

SecurityException - 如果当前线程不能修改该线程。

另请参见:

checkAccess(), suspend()

join

public final void join(long millis)

throws InterruptedException等待该线程终止的时间最长为 millis 毫秒。超时为 0 意味着要一直等下去。

参数:

millis - 以毫秒为单位的等待时间。

抛出:

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

join

public final void join(long millis)

throws InterruptedException

等待该线程终止的时间最长为 millis 毫秒。超时为 0 意味着要一直等下去。

参数:

millis - 以毫秒为单位的等待时间。

抛出:

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

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) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }      

join

public final void join(long millis,

int nanos)

throws InterruptedException

等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

参数:

millis - 以毫秒为单位的等待时间。

nanos - 要等待的 0-999999 附加纳秒。

抛出:

IllegalArgumentException - 如果 millis 值为负,则 nanos 的值不在 0-999999 范围内。

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

/**
     * Waits at most {@code millis} milliseconds plus
     * {@code nanos} nanoseconds for this thread to die.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @param  nanos
     *         {@code 0-999999} additional nanoseconds to wait
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value
     *          of {@code nanos} is not in the range {@code 0-999999}
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final synchronized void join(long millis, int nanos)
    throws InterruptedException {

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }      

join

public final void join()

throws InterruptedException

等待该线程终止。

抛出:

InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。

/**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);
    }      

GetterSetter

private volatile char  name[];
    private int            priority;
    private Thread         threadQ;
    private long           eetop;

    /* Whether or not to single_step this thread. */
    private boolean     single_step;

    /* Whether or not the thread is a daemon thread. */
    private boolean     daemon = false;

    /* JVM state */
    private boolean     stillborn = false;

    /* What will be run. */
    private Runnable target;

    /* The group of this thread */
    private ThreadGroup group;

    /* The context ClassLoader for this thread */
    private ClassLoader contextClassLoader;

    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;

    /* For autonumbering anonymous threads. */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    /*
     * The requested stack size for this thread, or 0 if the creator did
     * not specify a stack size.  It is up to the VM to do whatever it
     * likes with this number; some VMs will ignore it.
     */
    private long stackSize;

    /*
     * JVM-private state that persists after native thread termination.
     */
    private long nativeParkEventPointer;

    /*
     * Thread ID
     */
    private long tid;

    /* For generating thread ID */
    private static long threadSeqNumber;

    /* Java thread status for tools,
     * initialized to indicate thread 'not yet started'
     */

    private volatile int threadStatus = 0;


    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

    /**
     * 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
     */
    volatile Object parkBlocker;

    /* The object in which this thread is blocked in an interruptible I/O
     * operation, if any.  The blocker's interrupt method should be invoked
     * after setting this thread's interrupt status.
     */
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();      

测试

package testlang;

/**
 * @author CSDN@日星月云
 * @date 2022/10/25 18:48
 */
public class TestThread {
    public static void main(String[] args) {
        //方式一:继承Thread
        PrimeThread p = new PrimeThread(143);
        p.start();

        //方式二:实现Runnable
        PrimeRun p1 = new PrimeRun(143);
        new Thread(p1).start();
    }
}


class PrimeThread extends Thread {
    long minPrime;
    PrimeThread(long minPrime) {
        this.minPrime = minPrime;
    }

    public void run() {
        // compute primes larger than minPrime
        System.out.println(minPrime);
    }
}

class PrimeRun implements Runnable {
    long minPrime;
    PrimeRun(long minPrime) {
        this.minPrime = minPrime;
    }

    public void run() {
        // compute primes larger than minPrime
        System.out.println(minPrime);
    }
}      

附:Thread源码

package java.lang;
    /**
     * 操作系统在运行一个程序时,会为其创建一个进程,一个进程中可以创建多个线程, 这些线程都拥有各自的计数器,堆栈和局部变量等属性,
     * 并且可以访问共享的内存变量, 处理器根据时间片算法在线程之间进行高速切换,在宏观上给人以线程同时执行的感觉.
     *
     * 每个线程都有相应的优先级,从1到10,默认优先级为5,高优先级的线程获得CPU时间片优势大于低优先级的, 但是不是绝对,很多操作系统以及JVM版本并不认可线程的优先级的说法
     *
     * 每个线程都可以被设置为守护线程(Daemon),设置时在线程启动前设置,调用Thread.setDaemon(true),守护线程
     * 主要用于程序中后台调度以及支持性工作.当JVM中不存在Daemon线程时,JVM会退出,所以Daemon线程中的finally中的代码 不一定会执行
     *
     * 创建线程一般有两种方法: 集成Thread类,实现Runnable接口 实际上Thread也是实现Runable接口
     */
    public class Thread implements Runnable {
        /** static修饰,确保本地注册创建线程时执行,native修饰,调用其他语言的方法 */
        private static native void registerNatives();
        static {
            registerNatives();
        }
    
        private volatile char name[];   // 线程名,可以修改且对线程可见
        private int priority;   // 线程优先级,1到10,默认为5
        private Thread threadQ;
        private long eetop;
        
          /* 是否是单步执行*/
        private boolean single_step;
        
          /* 该线程是否是守护线程 */
        private boolean daemon = false; 
    
        /* JVM 状态 */
        private boolean stillborn = false;
    
        /* 要被执行的run方法 */
        private Runnable target;
    
        /* 线程所属线程组 */
        private ThreadGroup group;
    
        /* 线程的类加载器 */
        private ClassLoader contextClassLoader;
    
        /* 该线程继承的访问控制上下文 */
        private AccessControlContext inheritedAccessControlContext;
    
        /* 用于自动编号的匿名线程 ,默认线程编号*/
        private static int threadInitNumber;
    
        private static synchronized int nextThreadNum() {
            return threadInitNumber++;
        }
    
        /* 该线程的本地变量值,此map由ThreadLocal类进行维护,是一个维护线程本地变量的hashmap,hashmap的key为弱引用,可以增长对象的存活时间*/
        ThreadLocal.ThreadLocalMap threadLocals = null;
    
        /*该线程继承所得到本地变量值,此map由inheritableThreadLocals类维护*/
        ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    
        /*栈的深度,默认为0,此数字如何被使用完全取决于虚拟机自己;也有一些虚拟机会忽略此变量值.*/
        private long stackSize;

        /*本地线程终止后,JVM私有的一个状态值*/
        private long nativeParkEventPointer;

        /* 线程id*/
        private long tid;
    
        /* 用于生成线程Id */
        private static long threadSeqNumber;
    
        /* 为工具提供的线程状态值,初始化值标识当前线程还未运行*/
        private volatile int threadStatus = 0;

        /* 获取下一个线程id*/
        private static synchronized long nextThreadID() {
            return ++threadSeqNumber;
        }

        /* 线程共享变量d*/
        volatile Object parkBlocker;

        /* 阻塞变量,如果线程的中断状态被设置,则应该调用此线程阻塞对象的中断方法*/
        private volatile Interruptible blocker;
        private final Object blockerLock = new Object();

        /* 设置block的值,*/
        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;
    
        /* 返回当前正在执行线程对象的应用,这是一个native修饰的方法*/
        public static native Thread currentThread();
    
        /**
         * 提示线程调度器当前线程放弃CPU的使用,当然线程调度器可以忽略,
         * 让出CPU是一种启发式尝试,已改善线程之间的相对发展,否者将会过度利用CPU或者是其他线程获得不了CPU执行权限
         */
        public static native void yield();

        /* 睡眠millis毫秒数, 此方法的调用不会引起当前线程放弃任何监听器的所有权*/
        public static native void sleep(long millis) throws InterruptedException;

        /* 睡眠millis毫秒数,nanos纳秒数,,此方法的调用不会引起当前线程放弃任何监听器的所有权*/
        public static void sleep(long millis, int nanos) throws InterruptedException {
            // 毫秒值小于0,不合法
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
            // 纳秒小于0 或者大于等于100万(1秒),纳秒不合法
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException("nanosecond timeout value out of range");
            }
            // 纳秒大于等于50万,或者有纳秒数,毫秒数为0,毫秒数加1
            if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
                millis++;
            }
            // 调用睡眠方法
            sleep(millis);
        }

        /*利用当前访问控制上下文(AccessControlContext)来初始化一个线程*/
        private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
            init(g, target, name, stackSize, null);
        }

        /*初始化一个线程,私有方法,被各构造方法调用*/
        private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
            // 不允许,没有名字的线程出现
            if (name == null) {
                throw new NullPointerException("name cannot be null");
            }
            // 赋值线程名字
            this.name = name.toCharArray();
            // 获取当正在执行的线程,用该线程来创建新的线程
            Thread parent = currentThread();
            // 获得系统的安全管理器
            SecurityManager security = System.getSecurityManager();
            if (g == null) {
                // 线程的组为空 
                if (security != null) {
                    // 线程的组为空,从系统安全管理器中获得线程组
                    g = security.getThreadGroup();
                }
    
                //系统安全管理器为null,则使用当前执行线程的组 
                if (g == null) {
                    g = parent.getThreadGroup();
                }
            }
    
            /* 检查是否允许当前线程修改线程组的参数 */
            g.checkAccess();
    
            //是否受限访问
            if (security != null) {
                if (isCCLOverridden(getClass())) {
                    security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
                }
            }
            // 将线程组中的容器容量增加1
            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);
            // 继承父类的本地变量
            if (parent.inheritableThreadLocals != null)
                this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
            //设置栈的深度
            this.stackSize = stackSize;
            //设置线程id
            tid = nextThreadID();
        }

        /*重写Object的克隆方法,但是线程不允许克隆.*/
        @Override
        protected Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }

        /*无参构造,创建一个线程对象,线程组为安全管理器或者父线程的线程组,没有执行方法,名字默认,栈深度为0*/
        public Thread() {
            init(null, null, "Thread-" + nextThreadNum(), 0);
        }

        /*利用Runnable创建线程,有执行方法,其余均是默认状态,Runnable中有run方法*/
        public Thread(Runnable target) {
            init(null, target, "Thread-" + nextThreadNum(), 0);
        }

        /*利用Runnable创建线程,传入继承访问控制上下文*/
        Thread(Runnable target, AccessControlContext acc) {
            init(null, target, "Thread-" + nextThreadNum(), 0, acc);
        }

        /* 传入线程组以及Rannable构造*/
        public Thread(ThreadGroup group, Runnable target) {
            init(group, target, "Thread-" + nextThreadNum(), 0);
        }

        /* 传入线程名构造*/
        public Thread(String name) {
            init(null, null, name, 0);
        }

        /* 传入线程组以及线程名构造*/
        public Thread(ThreadGroup group, String name) {
            init(group, null, name, 0);
        }
    
         /* 传入Runnable对象以及线程名构造*/
        public Thread(Runnable target, String name) {
            init(null, target, name, 0);
        }

        /* 传入线程组,Runnable对象,线程名构造*/
        public Thread(ThreadGroup group, Runnable target, String name) {
            init(group, target, name, 0);
        }
    
        /* 传入线程组,Runnable对象,线程名构,栈的深度*/
        public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
            init(group, target, name, stackSize);
        }

        /** 
        * 线程启动方法
        * 此方法的调用会引起当前线程的执行;JVM会调用此线程的run()方法,
        * 并不会被主要方法线程or由虚拟机创建的系统组线程所调用
        * 任何向此方法添加的新功能方法在未来都会被添加到虚拟机中
        * 结果就是两个线程可以并发执行:当前线程(从调用的start方法返回)和另一个线程(它在执行run方法). 
        * 一个线程可以被调用多次.
        * 尤其注意:一个线程执行完成后可能并不会再被重新执行.
        */
        public synchronized void start() {
            //0状态值代表了NEW的状态.
            if (threadStatus != 0)
                // 不是新创建的状态抛出异常
                throw new IllegalThreadStateException();
    
            // 向线程组里添加此线程,注意:线程创建的时候只是将线程组中的容器容量增加1
            group.add(this);
    
            boolean started = false;
            try {
                // 使线程进入可运行状态(runnable)
                start0();
                started = true;
            } finally {
                try {
                    if (!started) {
                        // 启动失败,再线程组中删除改线程
                        group.threadStartFailed(this);
                    }
                } catch (Throwable ignore) {
    
                }
            }
        }
        
        /* 本地方法,使线程进入可运行状态(就绪)*/
        private native void start0();

        /*线程获得CPU执行权限后执行的方法,实际上是调用的Runnable中的run()*/
        @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }

        /*这是在run方法执行结束后,此方法由系统调用,用于在一个线程退出前做一些扫尾工作.*/
        private void exit() {
            if (group != null) {
                // 加锁执行,删除该线程
                group.threadTerminated(this);
                group = null;
            }
             // GC 回收,全部置为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;
        }

        /*停止方法,已过期,有风险,不建议使用*/
        @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());
        }
    
        /*停止方法,已过期,有风险,不建议使用*/
        @Deprecated
        public final synchronized void stop(Throwable obj) {
            throw new UnsupportedOperationException();
        }
    
         /**
         *  中断当前线程, 一般来说sleep(),join(),wait()在检查到线程的中断状态的时候,
         *  会抛出中断异常InteruptedExeption,以及清除线程的中断状态
         */
        public void interrupt() {
            if (this != Thread.currentThread())
                //校验当前运行线程是否有权限修改本线程相关属性
                checkAccess();
            // 设置阻塞锁
            synchronized (blockerLock) {
                Interruptible b = blocker;
                if (b != null) {
                    interrupt0();   // Just to set the interrupt flag
                    b.interrupt(this);
                    return;
                }
            }
            interrupt0();
        }
    
        /**
         * 判断当前线程是否是中断状态,线程的中断状态会被此方法清除,
         * 也就是如果此方法两次调用都成功,那么在第二次调用的返回结果为false 
         * 除非在第一次调用完后和第二次调用前,当前线程被再次中断
         * 因为在中断状态被调用线程并处于alive状态而忽略线程中断的情况会由于此方法的调用而受影响
         */
        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }

        /*判断当前线程是够是中断状态,线程的中断状态不会被此方法清除*/
        public boolean isInterrupted() {
            return isInterrupted(false);
        }

         /*本地方法,测试线程是否被中断. 中断状态会被重置or并不依赖于之前的中断清除的值.*/
        private native boolean isInterrupted(boolean ClearInterrupted);
    
         /*过期无用方法*/
        @Deprecated
        public void destroy() {
            throw new NoSuchMethodError();
        }

        /*本地方法, 测试当前线程是否处于存活状态,一个线程在死亡状态前都是存活状态*/
        public final native boolean isAlive();

        /* 过期方法*/
        @Deprecated
        public final void suspend() {
            checkAccess();
            suspend0();
        }
    
          /* 过期方法*/
        @Deprecated
        public final void resume() {
            checkAccess();
            resume0();
        }

         /*  设置当前线程的优先级,设置的优先级不能大于线程组的最大线程优先级*/
        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);
            }
        }

        /*  获取线程的优先级*/
        public final int getPriority() {
            return priority;
        }

         /*  设置当前线程的名字,同步方法*/
        public final synchronized void setName(String name) {
            checkAccess();
            this.name = name.toCharArray();
            if (threadStatus != 0) {
                setNativeName(name);
            }
        }

        /*   获取线程的名字*/
        public final String getName() {
            return new String(name, true);
        }

        /*  获取线程的线程组*/
        public final ThreadGroup getThreadGroup() {
            return group;
        }

        /*  返回线程所属线程组的线程数,估值*/
        public static int activeCount() {
            return currentThread().getThreadGroup().activeCount();
        }

        /*  将当前线程组以及子组所有活着的线程拷贝到参数数组中*/
        public static int enumerate(Thread tarray[]) {
            return currentThread().getThreadGroup().enumerate(tarray);
        }

         /*  过期方法*/
        @Deprecated
        public native int countStackFrames();

         /*  最多等待参数millis时长,当前线程就会死亡,参数为0时则需要继续等待*/
        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");
            }
            // 等待时长为0,继续等待
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
    
         /*  最多等待参数millis毫秒加nanos纳秒时长,当前线程就会死亡,参数为0时则需要继续等待*/
        public final synchronized void join(long millis, int nanos) throws InterruptedException {
    
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException("nanosecond timeout value out of range");
            }
    
            if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
                millis++;
            }
    
            join(millis);
        }
    
         /*  等待一直到线程死亡.*/
        public final void join() throws InterruptedException {
            join(0);
        }

         /*  此方法只用于debug*/
        public static void dumpStack() {
            new Exception("Stack trace").printStackTrace();
        }

         /*   将当前线程设定为守护线程or用户线程. 此方法在start前被调用.如果值为true,则此线程被设定为守护线程.*/
        public final void setDaemon(boolean on) {
            checkAccess();
            if (isAlive()) {
                throw new IllegalThreadStateException();
            }
            daemon = on;
        }

        /*  判断线程是否为守护线程*/ 
        public final boolean isDaemon() {
            return daemon;
        }
    
        /**
         * 确定当前运行的线程是否有权利更改此线程相关属性. 如果有安全管理器,则会将当前线程作为参数传入checkAccess()方法
         *  这可能会导致SecurityException异常的抛出
         */
        public final void checkAccess() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkAccess(this);
            }
        }

         /* 返回线程基本信息*/ 
        public String toString() {
            ThreadGroup group = getThreadGroup();
            if (group != null) {
                return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]";
            } else {
                return "Thread[" + getName() + "," + getPriority() + "," + "" + "]";
            }
        }

         /* 此方法返回此线程的上下文类加载器.*/ 
        @CallerSensitive
        public ClassLoader getContextClassLoader() {
            if (contextClassLoader == null)
                return null;
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                ClassLoader.checkClassLoaderPermission(contextClassLoader, Reflection.getCallerClass());
            }
            return contextClassLoader;
        }

         /* 设置线程上下文类加载器*/ 
        public void setContextClassLoader(ClassLoader cl) {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
            }
            contextClassLoader = cl;
        }

         /*当且仅当,当前线程持有指定对象的监听器锁时,返回返回true. 这一方法被设计的目的是:用于程序自身去声明它已经有某个对象的锁啦.*/ 
        public static native boolean holdsLock(Object obj);
        
         /* 空栈元素对象*/ 
        private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
    
        /**
         * 返回表示该线程堆栈转储的堆栈跟踪元素数组。 如果线程还没有start,or虽然start了,但是并没有被CPU调用过,or线程以及终止了,则返回数组长度为0.
         * 如果返回数组长度非0,则数组中第一个元素(索引为0)代表了栈的顶部,就是所有调用方法中距离现在时间最近的那个.
         * 数组的最后一个元素代表了栈的底部,这是所有调用方法中距离现在时间最远的那个.
         * 如果存在安全管理器,且这一线程又不是当前线程,则安全管理器的checkPermission()方法会被调用以查看
         * 一些虚拟机在某些情况下,可能会在栈跟踪时遗漏至少一个以上的栈.在极端情况下,虚拟机没有任何栈跟踪信息所以返回数组长度为0.
         */
        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();
            }
        }
    
        /**
         * 返回一个用于所有存活线程的栈跟踪信息的map. map的key是每个线程;value是对应线程的栈跟踪元素的一个数组.
         * 当此方法被调用时,可能有些线程正在执行.每一个线程的栈跟踪信息都代表了线程在某一时刻状态的快照且每一个栈跟踪信息 会在不同的时间得到.
         * 如果虚拟机中某一个线程没有栈跟踪信息则其数组长度为0.
         * 如果有安全管理器,则安全管理器的checkPermission方法会被调用以检查是否允许获取所有线程的栈跟踪信息.
         */
        public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
            // check for getStackTrace permission
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
                security.checkPermission(SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
            }
    
            // Get a snapshot of the list of all threads
            Thread[] threads = getThreads();
            StackTraceElement[][] traces = dumpThreads(threads);
            Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
            for (int i = 0; i < threads.length; i++) {
                StackTraceElement[] stackTrace = traces[i];
                if (stackTrace != null) {
                    m.put(threads[i], stackTrace);
                }
                // else terminated so we don't put it in the map
            }
            return m;
        }
        
         /* 运行时许可常量*/ 
        private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
            new RuntimePermission("enableContextClassLoaderOverride");
    
        /** cache of subclass security audit results */
        /* Replace with ConcurrentReferenceHashMap when/if it appears in a future
         * release */
        private static class Caches {
            /** cache of subclass security audit results */
            static final ConcurrentMap<WeakClassKey, Boolean> subclassAudits = new ConcurrentHashMap<>();
    
            /** queue for WeakReferences to audited subclasses */
            static final ReferenceQueue<Class<?>> subclassAuditsQueue = new ReferenceQueue<>();
        }
    
        /**
         * Verifies that this (possibly subclass) instance can be constructed without violating security constraints: the
         * subclass must not override security-sensitive non-final methods, or else the "enableContextClassLoaderOverride"
         * RuntimePermission is checked.
         */
        private static boolean isCCLOverridden(Class<?> cl) {
            if (cl == Thread.class)
                return false;
    
            processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
            WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
            Boolean result = Caches.subclassAudits.get(key);
            if (result == null) {
                result = Boolean.valueOf(auditSubclass(cl));
                Caches.subclassAudits.putIfAbsent(key, result);
            }
    
            return result.booleanValue();
        }
    
        /**
         * Performs reflective checks on given subclass to verify that it doesn't override security-sensitive non-final
         * methods. Returns true if the subclass overrides any of the methods, false otherwise.
         */
        private static boolean auditSubclass(final Class<?> subcl) {
            Boolean result = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                public Boolean run() {
                    for (Class<?> cl = subcl; cl != Thread.class; cl = cl.getSuperclass()) {
                        try {
                            cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
                            return Boolean.TRUE;
                        } catch (NoSuchMethodException ex) {
                        }
                        try {
                            Class<?>[] params = {ClassLoader.class};
                            cl.getDeclaredMethod("setContextClassLoader", params);
                            return Boolean.TRUE;
                        } catch (NoSuchMethodException ex) {
                        }
                    }
                    return Boolean.FALSE;
                }
            });
            return result.booleanValue();
        }
    
        private native static StackTraceElement[][] dumpThreads(Thread[] threads);
    
        private native static Thread[] getThreads();
    
        /**
         * 获取当前线程,线程id
         */
        public long getId() {
            return tid;
        }
    
        /* 线程状态枚举  */
        public enum State {

             // 新建窗台,创建后还没有执行start方法的线程
            NEW,
            
             //  运行中状态,包含在运行中的线程以及在等待CPU调度的线程
            RUNNABLE,

             // 阻塞状态,表示线程阻塞于锁
            BLOCKED,
    
            // 等待状态,一个线程处于wating状态,是因为调用了下面方法中的某一个: 1.Object.wait 2.Thread.join 3.LockSupport.park
            WAITING,
    
            /**
             *等待超时状态 线程等待指定时间. 这种状态的出现是因为调用了下面方法中的某一个:
                 1.Thread.sleep() 2.Object.wait() 3.Thread.join() 4.LockSupport.parkNanos(), 5.LockSupport.parkUntil()
             */
            TIMED_WAITING,
    
            // 终止状态,表示当前线程已经执行完毕。
            TERMINATED;
        }

         /*返回线程状态. 这一方法的设计目的:用于系统状态的监听,而非同步控制.  */
        public State getState() {
            // get current thread state
            return sun.misc.VM.toThreadState(threadStatus);
        }
    
        // Added in JSR-166
    
        /**
         * 由于未捕获异常而导致线程终止的函数接口处理器. 当一个线程由于未捕获异常而终止时,JVM将会使用getUncaughtExceptionHandler来查询此线程的UncaughtExceptionHandler,
         * 且会调用处理器handler的uncaughtException()方法,将此线程和其异常作为参数.
         * 如果一个线程没有它特定的UncaughtExceptionHandler,则它所属的线程组对象充当其UncaughtExceptionHandler.
         * 如果线程组对象没有处理异常的指定请求,它可以向前调用getDefaultUncaughtExceptionHandler的默认处理异常的方法.
         */
        @FunctionalInterface
        public interface UncaughtExceptionHandler {
            /**
             * 由于未捕获异常而导致线程终止的方法调用. 此方法抛出的任何异常都会被JVM忽略.
             */
            void uncaughtException(Thread t, Throwable e);
        }
    
        // null unless explicitly set
        private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
    
        // null unless explicitly set
        private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
    
        /**
         * 设定默认处理器用于处理:由于未捕获异常而导致的线程终止,且此线程还未定义任何其它的处理器.
         * 未捕获异常首先由本线程进行处理,然后由线程所属的线程组对象处理,最后由默认未捕获异常处理器进行处理.
         * 如果线程未设定明确的未捕获异常处理器,且线程的线程组(包括父线程组)也未指定,则此时默认处理器的uncaughtException
         * 方法会被执行.由于设定了默认的未捕获异常处理器,则应用能够更改未捕获异常的处理方法.
         * 注意:默认的未捕获异常处理器不应该经常使用线程的线程组对象,因为这会引起无限递归.
         */
        public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));
            }
    
            defaultUncaughtExceptionHandler = eh;
        }
    
        //当一个线程因未捕获异常而突然终止时,返回的默认处理器.
        public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
            return defaultUncaughtExceptionHandler;
        }
    
        //返回由于未捕获异常而导致线程中断的处理器.如果此线程无未捕获异常处理器,则返回此线程的线程组对象
        //如果此线程已经终止,则返回null.
        public UncaughtExceptionHandler getUncaughtExceptionHandler() {
            return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group;
        }
    
        /**
         * 设定一个由于未捕获异常而导致线程中断的处理器. 
         * 通过设定未捕获异常处理器,一个线程可以完全控制如何处理未捕获异常.
         * 如果没有设定未捕获异常,则线程组对象默认为其未捕获异常处理器.
         */
        public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
            checkAccess();
            uncaughtExceptionHandler = eh;
        }
    
        //将未捕获异常分发给处理器.这一方法通常被JVM调用.
        private void dispatchUncaughtException(Throwable e) {
            getUncaughtExceptionHandler().uncaughtException(this, e);
        }
    
        //删除指定map中那些在特定引用队列中已经排队的所有key
        static void processQueue(ReferenceQueue<Class<?>> queue, ConcurrentMap<? extends WeakReference<Class<?>>, ?> map) {
            Reference<? extends Class<?>> ref;
            while ((ref = queue.poll()) != null) {
                map.remove(ref);
            }
        }
    
      /**
     *  Weak key for Class objects.
     *  WeakReference类说明:弱引用对象(JVM四种引用中的弱引用),这并不妨碍它们的引用对象被最终化、定型,然后回收.弱引用最常用于实现规范化映射。
     **/
        static class WeakClassKey extends WeakReference<Class<?>> {
            /**
             * saved value of the referent's identity hash code, to maintain a consistent hash code after the referent has
             * been cleared
             */
            private final int hash;
    
            /**
             * Create a new WeakClassKey to the given object, registered with a queue.
             */
            WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
                super(cl, refQueue);
                hash = System.identityHashCode(cl);
            }
    
            /**
             * Returns the identity hash code of the original referent.
             */
            @Override
            public int hashCode() {
                return hash;
            }
    
            /**
             * Returns true if the given object is this identical WeakClassKey instance, or, if this object's referent has
             * not been cleared, if the given object is another WeakClassKey instance with the identical non-null referent
             * as this one.
             */
            @Override
            public boolean equals(Object obj) {
                if (obj == this)
                    return true;
    
                if (obj instanceof WeakClassKey) {
                    Object referent = get();
                    return (referent != null) && (referent == ((WeakClassKey)obj).get());
                } else {
                    return false;
                }
            }
        }
    
        // The following three initially uninitialized fields are exclusively
        // managed by class java.util.concurrent.ThreadLocalRandom. These
        // fields are used to build the high-performance PRNGs in the
        // concurrent code, and we can not risk accidental false sharing.
        // Hence, the fields are isolated with @Contended.
    
        /** The current seed for a ThreadLocalRandom */
        @sun.misc.Contended("tlr")
        long threadLocalRandomSeed;
    
        /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
        @sun.misc.Contended("tlr")
        int threadLocalRandomProbe;
    
        /** Secondary seed isolated from public ThreadLocalRandom sequence */
        @sun.misc.Contended("tlr")
        int threadLocalRandomSecondarySeed;
    
        /* Some private helper methods */
        private native void setPriority0(int newPriority);
    
        private native void stop0(Object o);
    
        private native void suspend0();
    
        private native void resume0();
    
        private native void interrupt0();
    
        private native void setNativeName(String name);
    }      

总结

  • Thread.State
  • 六种状态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED
  • start、start0
  • 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
  • 结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。
  • 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
  • run
  • 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
  • join
  • 等待该线程终止的时间最长为 millis 毫秒。超时为 0 意味着要一直等下去。
  • sleep
  • 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。
  • yield
  • 暂停当前正在执行的线程对象,并执行其他线程。

最后