Thread 类源码阅读

本想看看 AQS 相关代码,但是返现 Thread 状态与通信内容记不清楚,就先看下 Thread 类源码。
Thread 类的源码简单,因为主要逻辑都是 native 方法中。本文与其说是源码阅读,不如说是Java Doc 阅读。

构造函数

image.png

构造代码较简单,忽略,逻辑全部在 init 方法中。

/**
 * Initializes a Thread.
 *
 * @param g the Thread group
 * @param target the object whose run() method gets called
 * @param name the name of the new Thread
 * @param stackSize the desired stack size for the new thread, or
 *        zero to indicate that this parameter is to be ignored.
 * @param 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;

    // 新建子线程默认拥有和父线程相同的优先级和daemon属性
    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 (inheritThreadLocals && parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;

    /* Set thread ID */
    tid = nextThreadID();
}

逐一介绍 Thread 类的成员变量

private volatile String name; // 线程名称,可通过构造指定
private int priority; // Java 线程的优先级定义为从 1 到 10 的等级,默认为 5
private Thread threadQ; //
private long eetop; // 
private boolean single_step; // 
private boolean daemon = false; // 守护线程
private boolean stillborn = false; 
private Runnable target; // Runnable 对象
private ThreadGroup group; // 线程组
private ClassLoader contextClassLoader;
private AccessControlContext inheritedAccessControlContext;
private static int threadInitNumber;
ThreadLocalMap threadLocals = null; // 线程本地变量Map, 由 ThreadLocal 持有
ThreadLocalMap inheritableThreadLocals = null; // 可继承的线程本地变量,由 InheritableThreadLocal 持有
private long stackSize; // 线程要求的栈深度,有些VM会忽略,暂不深究
private long nativeParkEventPointer;
private long tid; // 线程ID
private static long threadSeqNumber; // 用户生成线程ID,计数用
private volatile int threadStatus = 0; // 线程状态,下文由单独描述
volatile Object parkBlocker;
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
public static final int MIN_PRIORITY = 1;
public static final int NORM_PRIORITY = 5;
public static final int MAX_PRIORITY = 10;
private static final StackTraceElement[] EMPTY_STACK_TRACE;
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION;
private volatile Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
private static volatile Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
@Contended("tlr")
long threadLocalRandomSeed;
@Contended("tlr")
int threadLocalRandomProbe;
@Contended("tlr")
int threadLocalRandomSecondarySeed;

线程状态, 注释异常详细,不再赘述。

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;
}

在介绍完 Thread 类的各个方法之后,再介绍线程状态转变的逻辑。

Thread 主要方法介绍

currentThread

public static native Thread currentThread(); // 获取当前线程

yield

public static native void yield(); // 暗示调度器让出当前线程的执行时间片,调度器可以选择忽略该暗示

sleep

public static native void sleep(long millis) throws InterruptedException;  // 当前执行线程休眠指定毫秒,在休眠期间,不释放任何当前线程持有的锁
// 当前执行线程休眠指定毫秒外加指定纳秒(四舍五入,毫秒加一),在休眠期间,不释放任何当前线程持有的锁
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);
}

interrupted

/**
 * Tests whether the current thread has been interrupted.  The
 * <i>interrupted status</i> of the thread is cleared by this method.  In
 * other words, if this method were to be called twice in succession, the
 * second call would return false (unless the current thread were
 * interrupted again, after the first call had cleared its interrupted
 * status and before the second call had examined it).
 * 返回当前线程是否被打断(打断标志是否被置位),会清除中断标志,即第二次调用会返回 false
 *
 * <p>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  <code>true</code> if the current thread has been interrupted;
 *          <code>false</code> otherwise.
 * @see #isInterrupted()
 * @revised 6.0
 */
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

dumpStack

/**
 * Prints a stack trace of the current thread to the standard error stream.
 * This method is used only for debugging.
 * 打印当前执行线程的栈信息
 *
 * @see     Throwable#printStackTrace()
 */
public static void dumpStack() {
    new Exception("Stack trace").printStackTrace();
}

以上都是静态方法,正对当前正在运行线程的操作。
下面开始介绍成员方法,针对某一线程的操作。

clone
抛出异常
start

/**
 * Causes this thread to begin execution; the Java Virtual Machine
 * calls the <code>run</code> method of this thread.
 * 触发线程开始执行;JVM 调用该线程的 run 方法
 * <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>
 * 结果是同时有两个线程是 running 状态, 一个调用 start 方法返回, 一个执行线程的 run 方法
 * 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".
     */
    // 检查状态必须为 0, 即 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 */
        }
    }
}
private native void start0();

run

// run 方法,就是运行 target 的 run 方法,不能当作新起一个线程
public void run() {
    if (target != null) {
        target.run();
    }
}

stop
停止线程,方法已经被 @Deprecated 注释,不在详细介绍
interrupt

/**
 * 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}.
 * 如果这个线程阻塞在Object.wait(),Thread.join(),Thread.sleep()上,那么该线程会收到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}.
 * 如果这个线程阻塞在InterruptibleChannel的IO操作上, 打断标志会被置位,并抛出 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.
 * 如果这个线程阻塞在 Selector 上,打断标志会被置位,那么该Selector的selection操作将会立即返回一个非0的结果,
 * 且Selector.wakeup()会被调用
 *
 * <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.
 * 打断一个非活状态( isAlive 方法,返回 false)的线程,无任何影响
 *
 * @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();
}

isInterrupted

/**
 * Tests whether this thread has been interrupted.  The <i>interrupted
 * status</i> of the thread is unaffected by this method.
 * 测试这个线程是否被中断
 *
 * <p>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  <code>true</code> if this thread has been interrupted;
 *          <code>false</code> 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);

destroy
被 @Deprecated 修饰,抛出异常
isAlive

/**
 * Tests if this thread is alive. A thread is alive if it has
 * been started and has not yet died.
 * 返回当前线程是否还活着,start()后且还没有死亡的线程均视为活着的线程
 *
 * @return  <code>true</code> if this thread is alive;
 *          <code>false</code> otherwise.
 */
public final native boolean isAlive();

suspend、resume、countStackFrames
被 @Deprecated 修饰
setPriority getPriority

/**
 * Changes the priority of this thread.
 * 修改线程优先级
 * <p>
 * First the <code>checkAccess</code> method of this thread is called
 * with no arguments. This may result in throwing a
 * <code>SecurityException</code>.
 * <p>
 * Otherwise, the priority of this thread is set to the smaller of
 * the specified <code>newPriority</code> and the maximum permitted
 * priority of the thread's thread group.
 *
 * @param newPriority priority to set this thread to
 * @exception  IllegalArgumentException  If the priority is not in the
 *               range <code>MIN_PRIORITY</code> to
 *               <code>MAX_PRIORITY</code>.
 * @exception  SecurityException  if the current thread cannot modify
 *               this thread.
 * @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);
    }
}

/**
 * Returns this thread's priority.
 * 返回线程优先级
 *
 * @return  this thread's priority.
 * @see     #setPriority
 */
public final int getPriority() {
    return priority;
}

setName、getName

/**
 * Changes the name of this thread to be equal to the argument
 * <code>name</code>.
 * 修改线程名称
 * <p>
 * First the <code>checkAccess</code> method of this thread is called
 * with no arguments. This may result in throwing a
 * <code>SecurityException</code>.
 *
 * @param      name   the new name for this thread.
 * @exception  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);
    }
}

/**
 * Returns this thread's name.
 * 获取线程名称
 *
 * @return  this thread's name.
 * @see     #setName(String)
 */
public final String getName() {
    return name;
}

getThreadGroup

/**
 * Returns the thread group to which this thread belongs.
 * This method returns null if this thread has died
 * (been stopped).
 * 返回所属线程组,如果该线程已死,返回null
 *
 * @return  this thread's thread group.
 */
public final ThreadGroup getThreadGroup() {
    return group;
}
/**
 * Returns an estimate of the number of active threads in the current
 * thread's {@linkplain java.lang.ThreadGroup thread group} and its
 * subgroups. Recursively iterates over all subgroups in the current
 * thread's thread group.
 * 返回当前线程所属的线程组及其子线程组的估算的活跃线程数目
 *
 * <p> The value returned is only an estimate because the number of
 * threads may change dynamically while this method traverses internal
 * data structures, and might be affected by the presence of certain
 * system threads. This method is intended primarily for debugging
 * and monitoring purposes.
 * 返回值是估算的,因为在该方法执行时,活跃线程是在动态变化的
 *
 * @return  an estimate of the number of active threads in the current
 *          thread's thread group and in any other thread group that
 *          has the current thread's thread group as an ancestor
 */
public static int activeCount() {
    return currentThread().getThreadGroup().activeCount();
}
/**
 * Copies into the specified array every active thread in the current
 * thread's thread group and its subgroups. This method simply
 * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])}
 * method of the current thread's thread group.
 * 复制当前线程组及其子线程组的活跃线程到数组中
 *
 * <p> An application might use the {@linkplain #activeCount activeCount}
 * method to get an estimate of how big the array should be, however
 * <i>if the array is too short to hold all the threads, the extra threads
 * are silently ignored.</i>  If it is critical to obtain every active
 * thread in the current thread's thread group and its subgroups, the
 * invoker should verify that the returned int value is strictly less
 * than the length of {@code tarray}.
 * 如果数组大小不够,会忽略多余的线程
 *
 * <p> Due to the inherent race condition in this method, it is recommended
 * that the method only be used for debugging and monitoring purposes.
 *
 * @param  tarray
 *         an array into which to put the list of threads
 *
 * @return  the number of threads put into the array
 *
 * @throws  SecurityException
 *          if {@link java.lang.ThreadGroup#checkAccess} determines that
 *          the current thread cannot access its thread group
 */
public static int enumerate(Thread tarray[]) {
    return currentThread().getThreadGroup().enumerate(tarray);
}

join

/**
 * Waits at most {@code millis} milliseconds for this thread to
 * die. A timeout of {@code 0} means to wait forever.
 * 最多等待指定毫秒数这个线程死亡,然后继续执行,参数 0 表示永远等待
 *
 * <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.
 * 使用 wait 方法和 isAlive 方法循环实现。当线程结束时,会调用自身的 notifyAll 方法。
 *
 * @param  millis
 *         the time to wait in milliseconds
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative
 *
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
//  亮点!亮点!亮点!亮点!同步方法,同步当前Thread对象,所以才能在其内部调用wait()
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;
        }
    }
}

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

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

setDaemon、isDaemon

/**

 * Marks this thread as either a {@linkplain #isDaemon daemon} thread
 * or a user thread. The Java Virtual Machine exits when the only
 * threads running are all daemon threads.
 * 标记线程为用户线程或者守护线程
 *
 * <p> This method must be invoked before the thread is started.
 * 该方法必须在 start 方法之前执行
 *
 * @param  on
 *         if {@code true}, marks this thread as a daemon thread
 *
 * @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;
}

/**
 * Tests if this thread is a daemon thread.
 * 返回是否时守护线程
 *
 * @return  <code>true</code> if this thread is a daemon thread;
 *          <code>false</code> otherwise.
 * @see     #setDaemon(boolean)
 */
public final boolean isDaemon() {
    return daemon;
}

checkAccess

/**
 * Determines if the currently running thread has permission to
 * modify this thread.
 * 判断当前执行线程是否有权限修改这个线程
 * <p>
 * If there is a security manager, its <code>checkAccess</code> method
 * is called with this thread as its argument. This may result in
 * throwing a <code>SecurityException</code>.
 *
 * @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);
    }
}

toString

getContextClassLoader、setContextClassLoader

/**
 * Returns the context ClassLoader for this Thread. The context
 * ClassLoader is provided by the creator of the thread for use
 * by code running in this thread when loading classes and resources.
 * If not {@linkplain #setContextClassLoader set}, the default is the
 * ClassLoader context of the parent Thread. The context ClassLoader of the
 * primordial thread is typically set to the class loader used to load the
 * application.
 * 返回这个线程的上下文类加载器。上下文类加载器有这个线程的创建者提供
 *
 * <p>If a security manager is present, and the invoker's class loader is not
 * {@code null} and is not the same as or an ancestor of the context class
 * loader, then this method invokes the security manager's {@link
 * SecurityManager#checkPermission(java.security.Permission) checkPermission}
 * method with a {@link RuntimePermission RuntimePermission}{@code
 * ("getClassLoader")} permission to verify that retrieval of the context
 * class loader is permitted.
 * 
 *
 * @return  the context ClassLoader for this Thread, or {@code null}
 *          indicating the system class loader (or, failing that, the
 *          bootstrap class loader)
 *
 * @throws  SecurityException
 *          if the current thread cannot get the context ClassLoader
 *
 * @since 1.2
 */
@CallerSensitive
public ClassLoader getContextClassLoader() {
    if (contextClassLoader == null)
        return null;
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        ClassLoader.checkClassLoaderPermission(contextClassLoader,
                                               Reflection.getCallerClass());
    }
    return contextClassLoader;
}

/**
 * Sets the context ClassLoader for this Thread. The context
 * ClassLoader can be set when a thread is created, and allows
 * the creator of the thread to provide the appropriate class loader,
 * through {@code getContextClassLoader}, to code running in the thread
 * when loading classes and resources.
 * 变更类加载器
 *
 * <p>If a security manager is present, its {@link
 * SecurityManager#checkPermission(java.security.Permission) checkPermission}
 * method is invoked with a {@link RuntimePermission RuntimePermission}{@code
 * ("setContextClassLoader")} permission to see if setting the context
 * ClassLoader is permitted.
 *
 * @param  cl
 *         the context ClassLoader for this Thread, or null  indicating the
 *         system class loader (or, failing that, the bootstrap class loader)
 *
 * @throws  SecurityException
 *          if the current thread cannot set the context ClassLoader
 *
 * @since 1.2
 */
public void setContextClassLoader(ClassLoader cl) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission("setContextClassLoader"));
    }
    contextClassLoader = cl;
}

holdsLock

/**
 * Returns <tt>true</tt> if and only if the current thread holds the
 * monitor lock on the specified object.
 * 返回是否持有指定对象锁 
 *
 * <p>This method is designed to allow a program to assert that
 * the current thread already holds a specified lock:
 * <pre>
 *     assert Thread.holdsLock(obj);
 * </pre>
 *
 * @param  obj the object on which to test lock ownership
 * @throws NullPointerException if obj is <tt>null</tt>
 * @return <tt>true</tt> if the current thread holds the monitor lock on
 *         the specified object.
 * @since 1.4
 */
public static native boolean holdsLock(Object obj);

简单介绍了 Thread 类的主要方法之后,我们再来看下,线程状态的转换。
上文提到,状态一共有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 和 TERMINATED 六种。状态之间的转换如下:


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容