1. 程式人生 > 程式設計 >Java Thread類 Java Doc和原始碼解讀

Java Thread類 Java Doc和原始碼解讀

寫在前面

這個類是一個非常重要的類,Java併發框架中的很多關鍵的Class原始碼多多少少都會用到Thread類的一些方法,如果你不懂那些方法的行為,你絕對無法完全看懂併發框架原始碼。所以這個類是必須要解讀的,這是基礎。

基礎知識

1. Java Doc 正文

1.1 相關內容

Thread類是Runnable類的一個實現類。它還有一個子類,ForkJoinWorkerThread。

1.2 概述

Thread類代表程式中執行任務的一個執行緒。JVM允許程式同時執行多個執行緒併發執行任務。所有的執行緒都有優先順序。高優先順序的執行緒會優先執行。所有的執行緒也可以被標記為守護的,也就是守護執行緒。如果執行緒A建立了執行緒B,那麼執行緒B的優先順序會與A相同,如果A是一個守護執行緒,那麼B也會繼承此特性。

當JVM啟動後,一般都會有一個非守護執行緒(某個類呼叫了main方法)。JVM會一直執行除非出現了以下情況:

  • 系統呼叫exit方法,直接退出JVM
  • 所有非守護執行緒都已經死掉,無論是正常執行還是丟擲了異常

有兩種建立執行緒的方法。

  1. 建立一個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();
複製程式碼
  1. 另一種建立執行緒的方式是去宣告一個Runnable介面的實現類。這個實現類去實現Runnable的run方法。然後把這個實現類作為構造器的引數傳給Thread,然後thread.start。程式碼如下:
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();
複製程式碼

所有的執行緒都有一個名字,這樣比較好識別。多個執行緒可能會有相同的名稱。如果執行緒的名字沒有被特別指定,那麼建立執行緒時,系統會給你生成一個,比如 thread-0。 還有,你向Thread的構造方法傳一個空的Runnable,會報NPE(空指標異常)。

假如面試的時候面試官問你個問題,在Java中有幾種建立執行緒的方式?看到這裡你應該知道答案是什麼了。如果你不看官方的Java Doc,你就無法確定到底有幾種方式。當然了,你可以去網上查帖子,但是誰也沒辦法給你保證網上那些人寫的帖子一定是對的,一定要自己親自去考量後才能給出肯定的答案,不然隨時都有翻車的可能。

1.3 內部類

1.3.1 Java執行緒的六種狀態 Thread.State

Thread.State是Thread中的一個內部類,關於Thread.State我單開了一篇文章,加了一些樣例程式碼加深理解和記憶,請點選這裡

1.3.2 子執行緒的異常處理 Thread.UncaughtExceptionHandler

Thread.UncaughtExceptionHandler也是一個內部類,關於Thread.UncaughtExceptionHandler我也單開了一篇文章,並且配合對應的場景去演示,有興趣可以去讀一讀,跑跑程式碼加深記憶,詳情請點選這裡

1.4 public 靜態變數

這三個變數都是描述Thread的優先順序

1.4.1 public static final int MIN_PRIORITY = 1

執行緒的最小優先順序

1.4.2 public static final int NORM_PRIORITY = 5

執行緒的預設優先順序

1.4.3 public static final int MAX_PRIORITY = 10

執行緒的最大優先順序

1.5 構造方法

1.5.1 public Thread()

分配一個新的thread。這個構造器和Thread (null,null,gname)是一個效果,gname是一個新生成的執行緒名。執行緒名的生成規則:"Thread-"+n,n為整數。

1.5.2 public Thread(Runnable target)

target - 傳遞一個執行任務,當呼叫thread.start之後,target.run方法會被執行,如果傳空,那麼這個執行緒就什麼也不做。

1.5.3 public Thread(ThreadGroup group,Runnable target)

group - 可以指定這個執行緒的執行緒組,如果執行緒組為空,會使用current thread的執行緒組

1.5.4 public Thread(String name)

name - 指定執行緒名

1.5.5 public Thread(ThreadGroup group,String name)

不多說了

1.5.6 public Thread(Runnable target,String name)

不多說了

1.5.7 public Thread(ThreadGroup group,Runnable target,String name)

不多說了

1.5.8 public Thread(ThreadGroup group,String name,long stackSize)

這個得說一下 重點關注stackSize這個引數。stack size是這個執行緒的執行緒棧大小,它是一個近似值,單位是byte。這個引數行為,主要取決於執行jvm的平臺。

在一些平臺,將stackSize調大可能會允許執行緒達到更深的遞迴深度。類似的,將stackSize調小可以節省記憶體空間,這樣同時存活的執行緒數會更高。stackSize引數、執行緒遞迴深度和併發數量的關係主要取決於作業系統是如何實現的。在某些平臺,設定stackSize可能不起作用。

JVM可以將stackSize的設定當做一種建議。如果你設定一個特別小的值,就是那種根本就不合理的值,JVM會將這個值替換為作業系統預設的最低值,相反,你設定一個特別大的(比如幾TB),JVM會替換成預設的最大值。同樣,JVM可以對你設定的值做一些權衡,然後適當的調高和調低(或者完全無視這個值)。

如果為stackSize引數指定一個0值,等於忽略這個值,這樣這個構造方法和Thread(ThreadGroup,Runnable,String)是等價的。

如果你要調整這個值,那麼你最好先做做測試。windows和linux系統的thread stack size可能不一樣,如果要對stack size做調整,務必保證你的測試覆蓋了所有程式可能執行的平臺,否則可能就會踩坑。

Parameters:
group - 執行緒組
target - 執行任務
name - 執行緒名
stackSize - 執行緒棧大小,單位是byte。如果設定為0等於忽略了這個引數,走預設值

1.6 方法

1.6.1 public static Thread currentThread()

返回當前正在執行的執行緒的引用。

1.6.2 public static void yield()

呼叫此方法會告訴執行緒排程器當前執行緒可以放棄對CPU的使用。排程器也可以忽略這個請求。開發這個方法的目的是嘗試改善多執行緒協作時某些執行緒對CPU佔用偏高的問題。這個方法的使用應該做好測試來保證這方法真的按照預期執行。

這個方法極少會被使用。不過它在debug或test時候可能比較有用,它有助於幫助重現bug。

1.6.3 public static void sleep(long millis)throws InterruptedException

呼叫此方法會導致當前正在執行的執行緒睡眠一段時間,實際睡眠時間取決於排程器和系統計時器。這個執行緒在睡眠時依然會持有鎖。
Parameters:
millis - 睡眠時間,單位是毫秒
Throws:
IllegalArgumentException - 毫秒引數如果傳了負數就拋這個異常
InterruptedException - 如果執行緒在睡眠時其他執行緒呼叫了這個執行緒的interrupt方法,會讓這個執行緒丟擲這個異常,執行緒可以根據自己的邏輯去做一些處理

1.6.4 public static void sleep(long millis,int nanos) throws InterruptedException

呼叫此方法會導致當前正在執行的執行緒睡眠指定的毫秒+納秒數,實際睡眠時間取決於排程器和系統計時器。這個執行緒在睡眠時依然會持有鎖。
Parameters:
millis - 睡眠的毫秒數
nanos - 0-999999 多餘的納秒數
Throws:
IllegalArgumentException - 如果毫秒引數是負數,或者納秒數>0 或 < 999999
InterruptedException - 如果執行緒在睡眠時其他執行緒呼叫了這個執行緒的interrupt方法,會讓這個執行緒丟擲這個異常,執行緒可以根據自己的邏輯去做一些處理

1.6.5 protected Object clone()throws CloneNotSupportedException

克隆一個執行緒沒有什麼意義,其實就是起一個新執行緒。你可以宣告一個自定義的執行緒來繼承Thread並重寫clone方法,即使你這樣做了,你呼叫這個方法它總會丟擲CloneNotSupportedExeception。所以這個方法可以忽略了,想都不要想。
Overrides:
方法要在子類中重寫
Returns:
這個例項的一個克隆,其實一直會丟擲異常,不會返回的
Throws:
CloneNotSupportedException - 永遠都丟擲這個異常

1.6.6 public void start()

讓這個執行緒開始執行,JVM會呼叫這個執行緒的run方法。 這個方法的呼叫會導致當前有兩個執行緒併發執行:一個是當前執行緒,另一個是你宣告並呼叫了start()的執行緒 一個執行緒不要start兩次,你呼叫了也不會執行兩次,會丟擲異常。

Throws:
IllegalThreadStateException - 如果執行緒已經start了,你再調start就丟擲異常

1.6.7 public void run()

如果這個執行緒使用一個特定的Runnable物件來初始化,那麼最終這個runnable物件的run方法會被執行。否則這個方法啥也不做。Thread的子類應該重寫這個方法。

1.6.8 public void interrupt()

打斷這個執行緒。如果這個執行緒被wait()、join()、sleep()方法阻塞,那麼這個執行緒的中斷標誌會被重置,而且收到一個InterruptedException。如果這個執行緒被一個Selector阻塞,那麼它收到interrupt方法時這個interrrupt狀態會被設定,而且會立即返回,可能會帶著一個非空值,就像select方法正常返回一樣。打斷一個不是alive狀態的執行緒是不會有效果的。

1.6.9 public static boolean interrupted()

檢測當前執行緒是否已經被interrupt。這個執行緒的interrupt狀態會被這個方法清除。也就是說,如果你呼叫這個方法兩次,那麼第二次一定會返回false,除非第二次呼叫interrupt之前,這個執行緒又被interrupt了。

Returns:
如果執行緒被interrupt過,那麼返回true,否則返回false
See Also:
isInterrupted()

1.6.10 public boolean isInterrupted()

檢測這個執行緒是否被interrupt。中斷狀態在呼叫此方法後不會有影響。

Returns:
如果執行緒被interrupt過,那麼返回true,否則返回false
See Also:
isInterrupted()

1.6.11 public final boolean isAlive()

檢驗這個執行緒是否是活躍的。一個執行緒已經被start而且還沒死亡的話,那就說這個執行緒是活的。

Returns: 活的就返回true。死的就返回false

1.6.12 public final void setPriority(int newPriority)

修改這個執行緒的優先順序。

Parameters:
newPriority - 新的優先順序
Throws: IllegalArgumentException - 如果優先順序不再這個範圍 [MIN_PRIORITY,MAX_PRIORITY]
SecurityException - 如果當前執行緒無法修改這個執行緒

1.6.13 public final int getPriority()

返回執行緒的優先順序

1.6.14 public final void setName(String name)

修改這個執行緒的名稱

1.6.15 public final String getName()

獲取這個執行緒的名稱

1.6.16 public final ThreadGroup getThreadGroup()

獲取這個執行緒所屬的執行緒組。如果這個執行緒已經死掉了,那麼這個方法會返回null。

1.6.17 public static int activeCount()

返回一個預估值,這個值代表當前執行緒組和執行緒子組的所有活躍執行緒數,只是預估值。遞迴的迭代所有這個執行緒所屬執行緒組與其執行緒子組。
之所以是一個預估的值,是因為這個活躍執行緒數量可能會動態的變化。這個方法主要用於監控和debugg。

1.6.18 public static int enumerate(Thread[] tarray)

將當前執行緒的執行緒和子執行緒組所有的活躍執行緒都拷貝到入參的陣列中。這個方法其實就是呼叫當前執行緒的ThreadGroup.enumerate(Thread[])。

一般你得呼叫activeCount方法統計一下你到底需要多大的array,如果入引陣列長度比較小,而實際執行緒多,多餘的執行緒會被忽略。

這個方法主要用於監控和debugg。

1.6.19 public final void join(long millis) throws InterruptedException

在這個執行緒死亡之前等待入參的毫秒數,也就是執行緒執行完了,但是還要再等一下。如果引數傳0就永遠等待。

1.6.20 public final void join(long millis,int nanos)throws InterruptedException

等待額外的納秒

1.6.21 public final void join()throws InterruptedException

就是join(0)

1.6.22 public static void dumpStack()

列印當前執行緒的棧資訊。這個方法只用於debug

1.6.23 public final void setDaemon(boolean on)

標記這個執行緒是一個守護執行緒還是一個使用者執行緒。JVM中只有守護執行緒時就會退出。這個方法必須在thread.start方法呼叫前使用

1.6.24 public final boolean isDaemon()

檢驗這個執行緒是不是守護執行緒

1.6.25 public final void checkAccess()

判斷當前的執行緒是否有許可權去修改這個執行緒。沒許可權就丟擲異常

1.6.26 public ClassLoader getContextClassLoader()

返回這個執行緒的ClassLoader。

1.6.27 public void setContextClassLoader(ClassLoader cl)

設定這個classloader

1.6.28 public static boolean holdsLock(Object obj)

判斷當前執行緒是否持有某個特定物件的鎖。

1.6.29 public StackTraceElement[] getStackTrace()

返回一個堆疊資訊的陣列代表這個執行緒轉儲。如果線上程start之前就呼叫這個方法;已經start但是還沒有真正的執行,CPU沒排程;已經結束,那麼會返回一個長度為0的陣列。如果返回的陣列長度不為0,那麼陣列的第一個元素就是執行緒最遠執行過的方法,陣列的最後一個元素是最近執行過的方法呼叫。

1.6.30 public static Map<Thread,StackTraceElement[]> getAllStackTraces()

返回一個map,包含了所有活躍執行緒和他們對應的StackTrace。這些堆疊資訊都是快照,也就是說堆疊資訊一直在變化,這個只是某個時刻的資訊。

1.6.31 public long getId()

返回這個執行緒的id。這個id是一個是一個正的long數字,當執行緒被建立時自動生成。這個id是唯一的,並且線上程消亡之前是無法更改的。但是當一個執行緒死掉了,這個執行緒的id可能會被其他執行緒使用。

1.6.32 public Thread.State getState()

返回這個執行緒的狀態。這個方法一般用於監控系統狀態,不是為了同步控制。

1.6.33 public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

設定預設的UncaughExceptionHandler。還記得UncauthExceptionHandler吧,線上程執行任務期間丟擲異常並且沒有被catch住時,會將Thread 和 異常物件傳遞給這個handler做一些後續的處理。 如果這個執行緒沒有其他的handler,那麼就會使用這個預設的handler。具體的可以看我另外一篇帖子,連結在上面。

1.6.34 public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()

返回這個defaultHandler,如果沒有預設的,返回null。

1.6.35 public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()

不多說了

1.6.36 public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

不多說了

2. Thread原始碼解讀

為了方便閱讀,我把Thread類的原始碼發到了掘金上,點選這裡可以檢視原版原始碼閱讀以下英文註釋

package java.lang;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;

public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
    //執行緒名稱,通過setName,init方法可以設定
    private volatile String name;
    //執行緒的優先順序
    private int            priority;
    //這個欄位原始碼沒有用到,具體有什麼作用不清楚
    private Thread         threadQ;
    //這個欄位原始碼沒有用到,具體有什麼作用不清楚
    private long           eetop;
    //這個欄位原始碼沒有用到,具體有什麼作用不清楚
    private boolean     single_step;
    //是否是守護執行緒
    private boolean     daemon = false;

    //這個欄位原始碼沒有用到,具體有什麼作用不清楚
    private boolean     stillborn = false;

    //執行緒要執行的任務
    private Runnable target;

    //這個執行緒的執行緒組
    private ThreadGroup group;

    //這個執行緒的classLoader
    private ClassLoader contextClassLoader;

    //Java的安全管理器 具體有什麼用,我還不清楚,後續搞清楚了會更新
    private AccessControlContext inheritedAccessControlContext;

    //如果new 執行緒時沒有指定名稱,會通過這個變數和下個方法生產一個序號作為執行緒name
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    //這個執行緒的ThreadLocal物件,有關ThreadLocal我們單開帖子去講
    ThreadLocal.ThreadLocalMap threadLocals = null;

    //這個具體什麼作用不清楚
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    //執行緒棧大小
    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;
    }

    /**
     * 這個和Lock框架有關,後續lock框架搞完再補充
     * 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();

    /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
     */
    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方法,返回當前執行緒的引用
     * 什麼是native方法,native方法就是jdk裡面一些使用C++或C實現的較底層的方法
     */
    public static native Thread currentThread();

    /**
     * native方法,表示當前執行緒放棄CPU資源,暫停執行
     */
    public static native void yield();

    /**
     * native方法,sleep一會兒
     */
    public static native void sleep(long millis) throws InterruptedException;

    /**
     * sleep一會兒,但是會判斷一下超時時間是否有效
     */
    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);
    }

    /**
     * 初始化執行緒,其實就是呼叫最全的那個init
     */
    private void init(ThreadGroup g,long stackSize) {
        init(g,target,name,stackSize,true);
    }

    /**
     * 初始化一個執行緒
     *
     * @param 執行緒組
     * @param 執行任務
     * @param 執行緒名稱
     * @param 執行緒棧大小
     * @param 安全控制器
     * @param 繼承的ThreadLocal,這個引數具體作用還需要再看一下
     */
    private void init(ThreadGroup g,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) {
            //檢查SecurityManager是否為空,如果不為空,使用SecurityManager的執行緒組
            if (security != null) {
                g = security.getThreadGroup();
            }

            //如果沒有SecurityManager,就是用父執行緒的執行緒組
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        //檢查是否有許可權
        g.checkAccess();

        //檢查是否有許可權
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }
        //執行緒組將這個執行緒加入到未啟動
        g.addUnstarted();
        
        this.group = g;
        //如果父執行緒是守護執行緒,那麼當前執行緒也會成為守護執行緒
        this.daemon = parent.isDaemon();
        //優先順序使用父執行緒的優先順序
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        //設定執行緒棧
        this.stackSize = stackSize;

        //呼叫靜態私有方法生成一個執行緒ID
        tid = nextThreadID();
    }

    /**
     * 看程式碼,永遠都會丟擲一個CloneNotSupportedException異常,Thread類不支援克隆
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    /**
     * 無參的構造方法,不多說了,上面已經很詳細了
     * 執行緒名使用nextThreadNum來設定
     */
    public Thread() {
        init(null,"Thread-" + nextThreadNum(),0);
    }

    /**
     * 不多說了
     */
    public Thread(Runnable target) {
        init(null,0);
    }

    /**
     * 傳一個安全控制器
     */
    Thread(Runnable target,AccessControlContext acc) {
        init(null,acc,false);
    }

    /**
     * 不多說
     */
    public Thread(ThreadGroup group,Runnable target) {
        init(group,0);
    }

    /**
     * 不多說
     */
    public Thread(String name) {
        init(null,0);
    }

    /**
     * 不多說
     */
    public Thread(ThreadGroup group,String name) {
        init(group,0);
    }

    /**
     * 不多說
     */
    public Thread(Runnable target,String name) {
        init(null,long stackSize) {
        init(group,stackSize);
    }

    /**
     * 啟動執行緒,這個方法是個同步的方法
     */
    public synchronized void start() {
        /**
         * 如果不是剛new出來的執行緒,拋異常
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        // 執行緒組新增此執行緒,然後unStarted可以減少,具體看ThreadGroup原始碼
        group.add(this);
        
        boolean started = false;
        try {
            //呼叫原生方法啟動執行緒
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                //啥也不幹
            }
        }
    }
    //native方法,這個方法才是真正啟動執行緒的方法
    private native void start0();

    /**
     * 不多說,這個是實現Runnable介面的方法
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    /**
     * 這個方法是JVM呼叫的,用來做一些清理工作
     */
    private void exit() {
        if (group != null) {
            group.threadTerminated(this);
            group = null;
        }
        //全都給置空
        target = null;
        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();
    }

    /**
     * 打斷執行緒
     */
    public void interrupt() {
        //判斷許可權
        if (this != Thread.currentThread())
            checkAccess();
        //這個鎖還不太清楚,要去研究一下Lock
        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                //native方法
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        //native方法
        interrupt0();
    }

    /**
     * 靜態方法,判斷當前執行緒是否被打斷,清除狀態
     */
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

    /**
     * 判斷是否打斷,不清除狀態
     */
    public boolean isInterrupted() {
        return isInterrupted(false);
    }

    /**
     * native方法,判斷執行緒是否被打斷了。
     * 這個執行緒的interrupted 狀態是否會被重置主要取決於這個引數
     */
    private native boolean isInterrupted(boolean ClearInterrupted);

    /**
     * 不要用這個方法,已經過時了
     */
    @Deprecated
    public void destroy() {
        throw new NoSuchMethodError();
    }

    /**
     * native方法,判斷這個執行緒是否還活著
     */
    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();
            }
            //這也是native方法
            setPriority0(priority = newPriority);
        }
    }

    /**
     * 獲取優先順序
     */
    public final int getPriority() {
        return priority;
    }

    /**
     * 設定執行緒的名稱
     */
    public final synchronized void setName(String name) {
        checkAccess();
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;
        if (threadStatus != 0) {
            //這是個native方法
            setNativeName(name);
        }
    }

    /**
     * 返回執行緒名
     */
    public final String getName() {
        return name;
    }

    /**
     * 獲取這個執行緒的執行緒組
     */
    public final ThreadGroup getThreadGroup() {
        return group;
    }

    /**
     * 獲取當前執行緒所線上程組的活躍執行緒數,這個值是動態的
     */
    public static int activeCount() {
        return currentThread().getThreadGroup().activeCount();
    }

    /**
     * 不多說了,詳細的說明單開ThreadGroup去講
     */
    public static int enumerate(Thread tarray[]) {
        return currentThread().getThreadGroup().enumerate(tarray);
    }

    /**
     * 過期了,不要用
     */
    @Deprecated
    public native int countStackFrames();

    /**
     * 執行緒任務執行完之後等待一段時間,核心方法是native的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()) {
                //native方法,傳0就是永遠等下去
                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");
        }
        //這裡納秒大於500000等於是+了一毫秒,否則按照毫秒去Wait
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }

    /**
     * 永遠的join下去
     */
    public final void join() throws InterruptedException {
        join(0);
    }

    /**
     * 列印堆疊,只有debugg的時候使用,平時別用
     */
    public static void dumpStack() {
        new Exception("Stack trace").printStackTrace();
    }

    /**
     * 設定守護執行緒標誌,記得是啟動前設定
     */
    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }

    /**
     * 判斷執行緒是否是守護執行緒
     */
    public final boolean isDaemon() {
        return daemon;
    }

    /**
     * 檢查許可權,後面會單開一個安全管理器的帖子去講,日常很少用到
     */
    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() + "," +
                            "" + "]";
        }
    }

    /**
     * 獲取ClassLoader,注意CallerSensitive這個註解,呼叫者必須有許可權
     * 涉及到ClassLoader的一些知識,後續單開帖子去講
     */
    @CallerSensitive
    public ClassLoader getContextClassLoader() {
        if (contextClassLoader == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(contextClassLoader,Reflection.getCallerClass());
        }
        return contextClassLoader;
    }

    /**
     * 設定這個ClassLoader
     */
    public void setContextClassLoader(ClassLoader cl) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("setContextClassLoader"));
        }
        contextClassLoader = cl;
    }

    /**
     * native方法,判斷是否有鎖
     */
    public static native boolean holdsLock(Object obj);
    
    //棧幀陣列
    private static final StackTraceElement[] EMPTY_STACK_TRACE
        = new StackTraceElement[0];

    /**
     * 獲取執行緒棧幀
     */
    public StackTraceElement[] getStackTrace() {
        if (this != Thread.currentThread()) {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkPermission(
                    SecurityConstants.GET_STACK_TRACE_PERMISSION);
            }
            
            if (!isAlive()) {
                return EMPTY_STACK_TRACE;
            }
            //dumpThreads這又是個native方法,其實是它來匯出執行緒棧的
            StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
            StackTraceElement[] stackTrace = stackTraceArray[0];
            // 上面呼叫isAlive雖然返回true,但是可能後面執行緒死掉了,就會導致
            //stackTrace為null
            if (stackTrace == null) {
                stackTrace = EMPTY_STACK_TRACE;
            }
            return stackTrace;
        } else {
            // Don't need JVM help for current thread
            return (new Exception()).getStackTrace();
        }
    }

    /**
     * 獲取所有執行緒的ThreadDump
     */
    public static Map<Thread,StackTraceElement[]> getAllStackTraces() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(
                SecurityConstants.GET_STACK_TRACE_PERMISSION);
            security.checkPermission(
                SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
        }

        // native方法,獲取所有活躍執行緒
        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);
            }
        }
        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 {
        
        NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;
    }

    /**
     * 獲取執行緒狀態
     */
    public State getState() {
        // get current thread state
        return sun.misc.VM.toThreadState(threadStatus);
    }

    /**
     * 執行緒異常處理器
     */
    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * 執行緒執行任務過程中出現未檢查異常時,JVM會呼叫這個方法
         */
        void uncaughtException(Thread t,Throwable e);
    }

    //處理器
    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;

    //預設的處理器
    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    /**
     * 設定預設的處理器
     */
    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;
    }

    /**
     * 如果處理器為空,就是用執行緒組作為處理器,因為執行緒組實現了這個介面
     */
    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);
    }

    /**
     * 清理引用佇列,關於引用,單開帖子去講
     */
    static void processQueue(ReferenceQueue<Class<?>> queue,ConcurrentMap<? extends
                             WeakReference<Class<?>>,?> map)
    {
        Reference<? extends Class<?>> ref;
        while((ref = queue.poll()) != null) {
            map.remove(ref);
        }
    }

    /**
     *  關於引用,單開帖子去講
     **/
    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;

    //以下全是原生方法
    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類的原始碼,其實不是很難理解,因為很多核心的操作都是使用native方法去實現的,但還是請牢記這些方法,都是基礎中的基礎!