Thread类源码解析

源码版本:jdk8

其中的部分论证和示例代码:Java_Concurrency


类声明:

Thread本身实现了Runnable接口

Runnable:任务,《java编程思想》中表示该命名不好,或许叫Task更好;

Thread:线程,执行任务的载体;

public class Thread implements Runnable 

构造方法:

构造时,可以指定线程组,线程运行任务Runnable对象,线程名和栈大小

线程的所有构造方法,都是通过init()实现

/**
 * Thread的所有public构造方法传入的inheritThreadLocals均为true
 * 只有一个权限为default的构造方法传入为false
 * 所有的构造方法实现均是调用了该方法
 */
private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc,
                  boolean inheritThreadLocals) {
    // 构造方法中传入的线程名不能为null
    // 默认线程名:"Thread-" + nextThreadNum()
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }
    this.name = name;
    // 被创建出来的线程是创建线程的子线程
    Thread parent = currentThread();
    // 新建线程的线程组
    // 如果构造方法传入的线程组为null,则通过这个流程来决定其线程组,通常,新建线程的线程组为其创建线程的线程组
    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;
    // 产生新的tid并设置
    tid = nextThreadID();
}
public long getId() {
    return tid;
}

上面的源码中有一个stackSize的参数,这个一般不会使用,其具体请参考javadoc.

默认线程名:"Thread-" + nextThreadNum():

/* For autonumbering anonymous threads. */
private static int threadInitNumber;
// 同步方法,保证tid的唯一性和连续性
private static synchronized int nextThreadNum() {
    return threadInitNumber++;
}
// 线程名可以被修改
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);
    }
}
 public final String getName() {
    return name;
}

ThreadGroup:

《java编程思想》有云:把ThreadGroup当做是一次不成功的尝试即可,不用理会

示例:ThreadGroupTest.java

public final ThreadGroup getThreadGroup() {
    return group;
}

Thread类默认的toString()中有使用其ThreadGroup:

public String toString() {
    ThreadGroup group = getThreadGroup();
    if (group != null) {
        return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]";
    } else {
        return "Thread[" + getName() + "," + getPriority() + "," + "" + "]";
    }
}

守护线程:

具体参考:Java 守护线程概述

示例:Daemon.java

/**
 * 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.
  */
public final void setDaemon(boolean on) {
    checkAccess();
    // 只有在线程开始前设置才有效
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}
public final boolean isDaemon() {
    return daemon;
}
// 返回当前线程是否还活着
// start()后且还没有死亡的线程均视为活着的线程
public final native boolean isAlive();

线程优先级和线程状态:

Java 线程状态与优先级相关的知识题目

示例:ThreadState.java

Priority.java

构造时如果不指定,默认线程优先级就是NORM_PRIORITY

public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

public final void setPriority(int newPriority) {
    ThreadGroup g;
    checkAccess();
    // 优先级范围 1~10
    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;
}
private native void setPriority0(int newPriority);
/**
 * A thread state.  A thread can be in one of the following states:
 * NEW:A thread that has not yet started is in this state.
 * RUNNABLE:A thread executing in the Java virtual machine is in this state.
 * BLOCKED:A thread that is blocked waiting for a monitor lock is in this state.
 * WAITING:A thread that is waiting indefinitely for another thread to
 *         perform a particular action is in this state.
 * TIMED_WAITING:A thread that is waiting for another thread to perform an action
 *         for up to a specified waiting time is in this state.
 * TERMINATED:A thread that has exited is in this state.
 * A thread can be in only one state at a given point in time.
 * These states are virtual machine states which do not reflect
 * any operating system thread states.
 * @since   1.5
 */
public enum State {
    // 创建后,但是没有start(),调用了start()后,线程才算准备就绪,可以运行(RUNNABLE)
    NEW,
    // 正在运行或正在等待操作系统调度
    RUNNABLE,
    // 线程正在等待监视器锁
    // 正在synchronized块/方法上等待获取锁,或者调用了Object.wait(),等待重新获得锁进入同步块
    BLOCKED,
    // 调用Object.wait(),Thread.join()或LockSupport.park()会进入该状态,注意这里的调用均为没有设置超时,
    // 线程正在等待其他线程进行特定操作,比如,调用了Object.wait()的线程在另一个线程调用Object.notify()/Object.notifyAll()
    // 调用了Thread.join()的线程在等待指定线程停止,join()的内部实现方式也是Object.wait(),只不过其Object就是线程对象本身
    WAITING,
    // 调用Thread.sleep(),Object.wait(long),Thread.join(long),
    // LockSupport.parkNanos(long),LockSupport.parkUntil(long)会进入该状态,
    // 注意,这里的调用均设置了超时
    TIMED_WAITING,
    // 线程执行完成,退出
    TERMINATED;
}
// @since 1.5
public State getState() {
    // get current thread state
    return sun.misc.VM.toThreadState(threadStatus);
}

这里关于线程状态需要特别注意,在网上有很多博客和书籍对线程状态进行讲解,其中很大一部分是错误的,对于BLOCKED,WAITING和TIMED_WAITING有所误解,认为一个线程在被从Object.wait()中被唤醒时,会立即进入Runnable状态,其实不是的:

一个线程在被从Object.wait()中被唤醒时,会立即进入BLOCKED状态,这时其并没有获得锁,只是被唤醒了,再次开始对Object的监视器锁进行竞争;只有在其竞争获得锁之后才会进入RUNNABLE状态.

在理解java线程状态时,建议直接看Thread.State的注释,就看英文版本,最贴切,没有杂质,也最正确,其他的所有书上的讲解似乎都有些偏颇

todo:

线程状态示例:ThreadState.java

线程优先级示例:Priority.java

关于wait()/notify()具体相关,请参考其他相关博客;

run():

如果是构造Thread对象的时候,传入了该对象预期执行的任务----Runnable对象时,执行该任务,否则,什么都不做,当然,可以通过集成Thread类,重写run(),来修改其行为:

/* What will be run. */
private Runnable target;
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

线程启动:

调用start()与调用run()的区别:懒得说

/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0;
// 启动线程,JVM会调用当前Thread对象的run() 
// 同步方法
public synchronized void start() {
    // A zero status value corresponds to state "NEW".
    // 如果调用时不是在线程状态不是NEW,则抛出IllegalThreadStateException
    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()来实现线程启动
        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();

线程打断:

示例:Interrupted.java

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

/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
 */
void blockedOn(Interruptible b) {
    synchronized (blockerLock) {
        blocker = b;
    }
}
/**
 * 打断当前执行线程
 * 如果当前线程阻塞在Object.wait(),Thread.join(),Thread.sleep()上,
 * 那么该线程会收到InterruptedException,且线程的打断标志会被清除;
 * 如果当前线程阻塞在InterruptibleChannel上,那么该InterruptibleChannel
 * 会被关闭,线程的打断标志会被置位,且当前线程会收到ClosedByInterruptException;
 * 如果当前线程阻塞在Selector上,那么该Selector的selection操作将会立即返回一个非0的结果,
 * 且Selector.wakeup()会被调用,线程的打断标志会被置位,
 * 如果上述情况均不存在,将当前线程的打断标志置位
 * 打断一个isAlive()返回false的线程没有效果,isInterrupted()仍然会返回false;
 */
public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();
    synchronized (blockerLock) {
        Interruptible b = blocker;
        // 在Interruptible上阻塞
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}
private native void interrupt0();

/**
 * 返回线程是否被打断(打断标志是否被置位)
 * 传入的参数决定是否该方法是否会清除终端标志位
 */
private native boolean isInterrupted(boolean ClearInterrupted);

public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

public boolean isInterrupted() {
    return isInterrupted(false);
}

关于isInterrupted()和interrupted()的区别,上述源码表现得很明显

而且,也体现了NIO的可中断中断实现方式

注意:interrupt()不能中断执行阻塞IO操作的线程.

线程的礼让—— yield() sleep() join():

关于Thread.sleep()和Object.wait()的区别:参考链接

示例:Yield.java

Join.java

/**
 * 暗示调度器让出当前线程的执行时间片,调度器可以选择忽略该暗示;
 * 该方法在用来调试和测试时可能很有用,可以用来重现需要特殊条件才能复现的bug;
 * 也可以用来进行并发优化等;
 */
public static native void yield();

/**
 * 当前执行线程休眠指定毫秒在休眠期间,不释放任何当前线程持有的锁;
 */
public static native void sleep(long millis) throws InterruptedException;

/**
 * 当前执行线程休眠指定毫秒在休眠期间,不释放任何当前线程持有的锁;
 * 如果当前被打断(该方法调用前或该方法调用时),抛出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");
    }
    // 纳秒最后还是转换成了毫秒233333
    // 可能是考虑都有些
    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }
    sleep(millis);
}
/**
 * 当前执行线程等待指定线程(也就是该调用发生的Thread对象)死后再继续执行;
 * 可以设置超时,如果设置超时为0,则为不设置超时;
 * 线程结束时(terminate),将会调用自身的notifyAll(),唤醒在该Thread对象上wait()的方法;
 * 如果该线程被打断,该方法将抛出InterruptedException,并将打断标志位清除
 */
// 同步方法,同步当前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");
    }
    // 使用isAlive()和wait()的循环实现
    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

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

被遗弃的方法——suspend() resume() stop():

示例:Deprecated.java

关于这些方法被遗弃的原因,具体参考:Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

/**
 * 挂起当前线程
 * 弃用原因:容易导致死锁
 */
@Deprecated
public final void suspend() {
    checkAccess();
    suspend0();
}
/**
 * 从suspend()中恢复线程运行
 * 弃用原因:容易导致死锁
 */
@Deprecated
public final void resume() {
    checkAccess();
    resume0();
}
/**
 * 强制线程停止执行;
 * 通过抛出一个ThreadDeath的方式来停止线程;
 * 废弃原因:stop()会师范所有已持有的锁的监视器,如果存在之前被这些监视器保护的对象处于一个不连续
 * 的状态(inconsistent state),这些被损坏的对象将会对其他线程可见,出现不可预期的行为;
 */
@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());
}

ThreadLocal:

在Thread类中有两个与ThreadLocal相关的成员变量

具体有关ThreadLocal,请参考:

一个故事讲明白线程的私家领地:ThreadLocal

ThreadLocal源码解读

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

ClassLoader:

关于ClassLoader,我暂时知道的也不多,先知道这个,以后有机会专门研究一下ClassLoader:

/* The context ClassLoader for this thread */
private ClassLoader contextClassLoader;
/**
 * 当前线程的ClassLoader,默认创建时是父线程的ClassLoader
 * @return  the context ClassLoader for this Thread, or {@code null}
 *          indicating the system class loader (or, failing that, the
 *          bootstrap class loader)
 * @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;
}
/**
 * @param  cl
 *         the context ClassLoader for this Thread, or null  indicating the
 *         system class loader (or, failing that, the bootstrap class loader)
 * @since 1.2
 */
public void setContextClassLoader(ClassLoader cl) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission("setContextClassLoader"));
    }
    contextClassLoader = cl;
}

线程栈轨迹:

// 特殊编程技巧
private static final StackTraceElement[] EMPTY_STACK_TRACE
        = new StackTraceElement[0];
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads();

// 打印当前线程的栈轨迹(StackTrace),通过新建一个异常的方式实现
// 注意:这是一个静态方法
public static void dumpStack() {
    new Exception("Stack trace").printStackTrace();
}
/**
 * 获得栈轨迹,返回的是一个数组
 * 数组的第0个栈轨迹为最近调用的栈轨迹
 * @since 1.5
 */
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);
        }
        // 不是活着的,返回的栈轨迹长度为0
        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) {
            // 这样就不会返回null,调用者也无需判断null了
            stackTrace = EMPTY_STACK_TRACE;
        }
        return stackTrace;
    } else {
        // Don't need JVM help for current thread
        return (new Exception()).getStackTrace();
    }
}
/**
 * 返回所有线程的栈轨迹
 * @since 1.5
 */
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;
}

UncaughtExceptionHandler:

示例:UncaughtExceptionHandlerEx.java

// null unless explicitly set
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
// null unless explicitly set
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
/**
 * 设置UncaughtExceptionHandler,该设置对所有线程有效
 * 如果自身没有设置,则交给其线程组的UncaughtExceptionHandler处理,如果再没有,
 * 则交给默认的的UncaughtExceptionHandler处理,也即这里设置的UncaughtExceptionHandler处理
 * 注意这里的设置不应该设置为线程的线程组,这样的设置会造成死循环
 * @since 1.5
 */
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));
    }
     defaultUncaughtExceptionHandler = eh;
 }
/**
 * 返回默认的UncaughtExceptionHandler,该UncaughtExceptionHandler对所有线程有效
 * 这是一个静态方法
 * @since 1.5
 */
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
    return defaultUncaughtExceptionHandler;
}
/**
 * 返回该线程的UncaughtExceptionHandler,如果没有,返回该线程的线程组
 * ThreadGroup本身实现了UncaughtExceptionHandler接口
 * @since 1.5
 */
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
    return uncaughtExceptionHandler != null ?
        uncaughtExceptionHandler : group;
}
/**
 * 设置该线程的UncaughtExceptionHandler
 */
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
    checkAccess();
    uncaughtExceptionHandler = eh;
}
/**
 * uncaught exception 分发给UncaughtExceptionHandler
 * 该方法被JVM调用
 */
private void dispatchUncaughtException(Throwable e) {
    getUncaughtExceptionHandler().uncaughtException(this, e);
}

其他:

// 返回当前语句执行的线程
public static native Thread currentThread();
// 不能克隆线程
@Override
protected Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
}
/**
 * 返回该线程是否持有指定对象的监视器锁
 * @since 1.4
 */
public static native boolean holdsLock(Object obj);

猜你喜欢

转载自www.cnblogs.com/jamesvoid/p/10011694.html