【Java】JDK源碼分析——Thread

一.概述

      Java虛擬機允許應用程序同時運行多個運行線程。
      每個線程都有優先級,優先級高的線程可以被優先執行。當一個線程中創建了另一個新線程,新線程的優先級默認等於這個線程的優先級。只有守護線程創建的線程纔是守護線程。
      當一個Java虛擬機啓動時,通常會啓動一個非守護線程,來運行main方法。虛擬機將繼續執行此線程,直到以下情況發生:
      1)調用Runtime類的exit方法,並且安全管理器允許退出操作發生。
      2)除了守護線程之外的所有線程都已經死亡。即線程內代碼全部執行完返回,或線程運行時拋出異常。
      每個線程都有一個名字,用於識別線程創建的目的。多個線程可能有相同的名字。若創建了一個沒有指定名字的線程,則會自動爲其生成一個名字。
Thread.java中的相關代碼:

public class Thread implements Runnable {
    // native方法
	private static native void registerNatives();
	// 靜態代碼塊初始化
    static {
        registerNatives();
    }}

1.實現了Runnable接口,可以在線程中運行。
2.在靜態代碼塊中調用registerNatives方法,確保該方法第一個執行。registerNatives方法用於動態註冊native方法,將java方法和native方法進行關聯。

二.源碼解析

1.重要的全局變量

Thread.java中的相關代碼:

	private volatile String name; // 用於記錄線程的名字

	private int priority; // 用於記錄線程的優先級

	private boolean daemon = false; // 用於表示線程是否爲守護線程

	private Runnable target; // 用於保存線程要執行的代碼

	private ThreadGroup group; // 用於記錄線程所在的組

	private ClassLoader contextClassLoader; // 用於保存上下文類加載器

	// 用於根據封裝的上下文對系統資源訪問做出決策
	private AccessControlContext inheritedAccessControlContext;

	private static int threadInitNumber; // 用於匿名線程的自動編號

	ThreadLocal.ThreadLocalMap threadLocals = null; // 用於保存當前線程共享的對象

	// 用於保存從父線程繼承的共享對象
	ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; 

	private long stackSize; // 當前線程請求的堆棧大小,默認爲0

	private long tid; // 用於保存線程ID

	private static long threadSeqNumber; // 用於自動生成線程ID

	private volatile int threadStatus = 0; // 用於表示線程的狀態,0表示線程尚未啓動

	// 在可中斷I/O操作中阻塞此線程的對象(如果有的話)。
	// 應在設置此線程的中斷狀態後調用攔截器的中斷方法。
	private volatile Interruptible blocker;

	private final Object blockerLock = new Object(); // 用於同步鎖

	public final static int MIN_PRIORITY = 1; // 線程最小優先級

	public final static int NORM_PRIORITY = 5; // 線程默認的優先級

	public final static int MAX_PRIORITY = 10; // 線程最大優先級

	// 允許子類重寫上下文類加載器權限
	private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
                    new RuntimePermission("enableContextClassLoaderOverride");
                    

2.內部枚舉類State

用來表示線程的狀態。
Thread.java中的相關代碼:

    public enum State {
        // 尚未啓動的線程的狀態
        NEW,

        // 可運行的線程的狀態
        // 可能在Java虛擬機中執行,也可能在等在操作系統的其它資源
        RUNNABLE,

        // 獲取不到鎖的線程的狀態
        // 阻塞狀態的線程可能正在等待獲取鎖來執行同步方法或代碼塊
        // 或在調用wait方法釋放鎖後,又需要鎖來執行同步方法或代碼塊
        BLOCKED,

        // 等待的線程的狀態
        // 等待狀態的線程正在等待另一個線程的特定操作
        // 調用wait方法不指定超時時間、調用join方法不指定超時時間,
		// 線程將進入該狀態
        // 一個線程調用鎖對象的wait方法,需要等待另一個線程調用該鎖對象
        // 的notify 或notifyAll方法
        // 一個線程調用join方法,需要等待一個指定的線程終止
        WAITING,

        // 指定了等待時間等待的線程的狀態
        // 調用sleep方法、調用wait方法指定超時時間、調用join方法指定超時時間
        // 線程將處於該狀態
        TIMED_WAITING,

        // 終止的線程的狀態
        // 線程已經執行完畢
        TERMINATED;
	}

3. nextThreadNum方法

當創建線程不指定線程名稱時,調用此方法產生編號作爲線程名稱的一部分。
Thread.java中的相關代碼:

	private static synchronized int nextThreadNum() {
    	// 返回,自增
        return threadInitNumber++;
	}

4. nextThreadID方法

用於創建線程ID。
Thread.java中的相關代碼:

	private static synchronized long nextThreadID() {
    	// 自增,返回
        return ++threadSeqNumber;
    }

5.常用的構造方法

1)無參數

Thread.java中的相關代碼:

	public Thread() {
    	// 調用四個參數的init方法
    	// 默認線程名爲”Thread-自增編號“
    	// 堆棧大小0,表示忽略該參數
        init(null, null, "Thread-" + nextThreadNum(), 0);
	}

2)參數爲Runnable

Thread.java中的相關代碼:

	public Thread(Runnable target) {
    	// 調用四個參數的init方法
    	// 保存target,默認線程名爲”Thread-自增編號“
    	// 堆棧大小0,表示忽略該參數
        init(null, target, "Thread-" + nextThreadNum(), 0);
	}

3)參數爲String

Thread.java中的相關代碼:

	public Thread(String name) {
    	// 調用四個參數的init方法
    	// 堆棧大小0,表示忽略該參數
        init(null, null, name, 0);
	}

4)參數爲ThreadGroup、Runnable、String、long

Thread.java中的相關代碼:

    public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
    	// 調用四個參數的init方法
        init(group, target, name, stackSize);
	}

5)四個參數的init方法

Thread所有的構造方法都調用該方法來實現,用來對線程進行初始化。
Thread.java中的相關代碼:

    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        // 調用五個參數的init方法,默認AccessControlContext爲空
        init(g, target, name, stackSize, null);
	}

6)五個參數的init方法

線程初始化的核心實現。相比四個參數的init方法,多了一個AccessControlContext類型的參數。
Thread.java中的相關代碼:

    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;

        // 獲取創建當前線程的線程,相當於當前線程的父線程
        Thread parent = currentThread();
        // 獲取安全管理器,默認是關閉的
        SecurityManager security = System.getSecurityManager();
        // 若線程組爲空
        if (g == null) {

            // 若開啓了安全管理器
            if (security != null) {
                // 獲取安全管理器的線程組
                g = security.getThreadGroup();
            }

            // 若安全管理器沒有配置線程組
            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()))
            // 調用方法,將父線程的上下文類加載器保存到全局變量

            // 因爲當父線程的類可以不違法安全約束創建實例,說明他可能存在子類,
            // 即子類化。由於多態,調用getContextClassLoader可能由子類實現
            this.contextClassLoader = parent.getContextClassLoader();
        else // 若安全管理器開啓,並且創建父線程的類的實例違反安全約束
            // 調用靜態變量,將父線程的上下文類加載器保存到全局變量

            // 因爲創建父線程類的實例違反安全規約,所以不可能存在子類
            // 因此直接從父類的靜態變量中獲取
            this.contextClassLoader = parent.contextClassLoader;

        // 若存取控制上下文爲空,從AccessController中獲取
        // 否則直接保存到全局變量
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        // 保存線程需要執行的Runnable對象
        this.target = target;
        // 設置線程優先級
        setPriority(priority);
        // 若父線程中存在繼承的ThreadLocal
        if (parent.inheritableThreadLocals != null)
            // 則根據父進程中繼承的ThreadLocal創建一個ThreadLocalMap對象
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        // 保存堆棧大小到全局變量
        this.stackSize = stackSize;

        // 設置線程ID
        tid = nextThreadID();
    }

6. currentThread方法

獲取當前執行的線程。
Thread.java中的相關代碼:

	public static native Thread currentThread();

7. setPriority方法

設置線程優先級。
Thread.java中的相關代碼:

	public final void setPriority(int newPriority) {
        ThreadGroup g;
        // 檢查當前運行的線程是否擁有修改此線程的權限
        // 詳解在1)處
        checkAccess();
        // 若要設置的線程優先級超過最大優先級或小於最小優先級,則拋出異常
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        // 獲取線程組,若線程組不爲空
        // 詳解在2)處
        if((g = getThreadGroup()) != null) {
            // 若要設置的優先級超過了線程組的最大優先級
            if (newPriority > g.getMaxPriority()) {
                // 將要設置的優先級改爲線程組的最大優先級
                newPriority = g.getMaxPriority();
            }
            // 將優先級保存到全局變量
            // 調用setPriority0方法設置線程優先級
            // 詳解在3)處
            setPriority0(priority = newPriority);
        }
    }

1)checkAccess方法

檢查當前運行的線程是否擁有修改此線程的權限。
Thread.java中的相關代碼:

	public final void checkAccess() {
    	// 獲取安全管理器
        SecurityManager security = System.getSecurityManager();
        // 若開啓了安全管理
        if (security != null) {
            // 通過安全管理器檢查當前運行的線程是否擁有修改此線程的權限
            security.checkAccess(this);
        }
	}

2)getThreadGroup方法

獲取線程組。
Thread.java中的相關代碼:

	public final ThreadGroup getThreadGroup() {
        // 返回全局變量
        return group;
    }

3)setPriority0方法

設置線程優先級的核心方法。
Thread.java中的相關代碼:

	private native void setPriority0(int newPriority);

8. start方法

啓動線程。
調用該方法將使JVM執行線程的run方法。
Thread.java中的相關代碼:

	public synchronized void start() {
        // 若當前線程的狀態不爲0,即不是新創建尚未啓動的狀態
        if (threadStatus != 0)
            // 則拋出異常
            throw new IllegalThreadStateException();

        // 通知線程組,該線程已啓動
        group.add(this);

        // 用於判斷啓動狀態,設置false
        boolean started = false;
        try {
            // 啓動線程
            // 詳解在1)處
            start0();
            // 設置true
            started = true;
        } finally {
            // 若發生異常
            try {
                // 若線程沒有啓動
                if (!started) {
                    // 通知線程組線程啓動失敗
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                // 若start0方法拋出異常,則什麼都不做,它的值會傳給調用的堆棧。
            }
        }
    }

1)start0方法

線程啓動的核心方法。
Thread.java中的相關代碼:

	private native void start0();

9. run方法

線程執行的核心方法。
若該線程通過傳入Runnable對象創建,則調用Runnable的run方法。
若該線程通過繼承Thread類實現,則需要重寫Run方法。
Thread.java中的相關代碼:

    @Override
	public void run() {
    	// 若target不爲空,即線程通過傳入Runnable對象創建
        if (target != null) {
            // 調用run方法
            target.run();
        }
    }

10. exit方法

該方法被系統調用,用於在線程退出前,對線程進行清理。
Thread.java中的相關代碼:

	private void exit() {
    	// 若線程組不爲空
        if (group != null) {
            // 通知線程組
            group.threadTerminated(this);
            // 釋放引用
            group = null;
        }
        // 釋放Runnable對象
        target = null;
        // 釋放其它資源
        threadLocals = null;
        inheritableThreadLocals = null;
        inheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }

11. interrupt方法

用於中斷一個線程。
Thread.java中的相關代碼:

	public void interrupt() {
    	// 若調用該方法的線程不是本線程
        if (this != Thread.currentThread())
            checkAccess(); // 檢查權限,是否允許訪問

        // 同步鎖
        synchronized (blockerLock) {
            // 獲取中斷攔截器
            Interruptible b = blocker;
            // 若中斷攔截器不爲空
            if (b != null) {
                // 設置線程中斷標誌位
                // 詳解在1)處
                interrupt0();
                // 調用中斷攔截器的方法
                b.interrupt(this);
                // 返回
                return;
            }
        }
        // 若沒有中斷攔截器,直接設置線程中斷標誌位
        interrupt0();
	}

1)interrupt0方法

中斷核心方法,該方法會設置線程中斷標誌位。
Thread.java中的相關代碼:

	private native void interrupt0();

12. interrupted方法

判斷當前線程是否中斷。
調用該方法將清除線程的中斷標誌位。
Thread.java中的相關代碼:

	public static boolean interrupted() {
    	// 獲取當前線程,調用isInterrupted方法判斷
        return currentThread().isInterrupted(true);
    }

13. isInterrupted方法

判斷調用該方法的線程對象是否中斷

1)無參數

Thread.java中的相關代碼:

	public boolean isInterrupted() {
    	// 調用了重載方法
        return isInterrupted(false);
    }

2)參數爲boolean

判斷線程中斷的核心方法。
中斷狀態的將被重置。重置的值不取決於參數ClearInterrupted。
Thread.java中的相關代碼:

	private native boolean isInterrupted(boolean ClearInterrupted);

14. isAlive方法

判斷線程是否存活。
存活即線程開始運行但並沒有死亡的期間。
Thread.java中的相關代碼:

	public final native boolean isAlive();

15. getPriority方法

獲取線程優先級。
Thread.java中的相關代碼:

	public final int getPriority() {
    	// 直接返回
        return priority;
    }

16. setName方法

設置線程的名字。
Thread.java中的相關代碼:

	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層處理
            // 詳解在1)處
            setNativeName(name);
        }
    }

1)setNativeName方法

設置線程名字的核心方法。
Thread.java中的相關代碼:

	private native void setNativeName(String name);

17. getName方法

獲取線程的名字。
Thread.java中的相關代碼:

	public final String getName() {
        // 直接返回
        return name;
    }

18. getThreadGroup方法

獲取線程組。
Thread.java中的相關代碼:

	public final ThreadGroup getThreadGroup() {
    	// 直接返回
        return group;
    }

19. activeCount方法

返回當前線程的線程組及其子線程組中所有活躍線程的數量。
Thread.java中的相關代碼:

	public static int activeCount() {
    	// 獲取當前線程,獲取線程組,遍歷統計
        return currentThread().getThreadGroup().activeCount();
    }

20. join方法

1)不指定超時時間

當前線程等待在當前線程中調用該方法的線程死亡。
Thread.java中的相關代碼:

	public final void join() throws InterruptedException {
    	// 調用重載方法,超時時間爲0
        join(0);
    }

2)指定超時時間

若在指定時間內調用該方法的線程沒有執行完畢,則等待的線程將不再等待。
Thread.java中的相關代碼:

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

        // 若指定毫秒小於0,則拋出異常
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        // 若納秒小於0或大於999999,則拋出異常
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        // 若納秒超過了500000,則化零爲整,毫秒加一
        // 若納秒不爲零且毫秒爲0,則設置最小時間1毫秒
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        // 調用重載方法
        join(millis);
	}

重載的join方法。
最多等待mills毫秒來讓線程死亡,參數爲0表示永久等待。
Thread.java中的相關代碼:

    public final synchronized void join(long millis)
	throws InterruptedException {
    	// 獲取系統當前時間作爲時間基準
        long base = System.currentTimeMillis();
        // 用於計算當前時間到base時間的間隔
        long now = 0;

        // 若等待時間小於0,則拋出異常
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        // 若等待時間爲0,說明是永久等待
        if (millis == 0) {
            // 循環,若調用join方法的線程活躍
            while (isAlive()) {
                // 調用join方法所在的線程永久等待
                wait(0);
            }
        } else { // 不是永久等待
            // 循環,若調用join方法的線程活躍
            while (isAlive()) {
                // 計算還需要等待的時長
                long delay = millis - now;
                // 若還需要等待的時長小於0,則跳出循環
                if (delay <= 0) {
                    break;
                }
                // 調用join方法所在的線程等待delay毫秒,超時放棄等待
                wait(delay);
                // 計算目前已經等待的時間
                now = System.currentTimeMillis() - base;
            }
        }
	}

注意:如在線程A中調用線程B的join方法,B爲調用join方法的線程,A爲調用join方法所在的線程。由於join方法中調用了wait方法,因此線程A阻塞等待,線程B正常執行。

21. setDaemon方法

用於標記一個線程是守護線程還是用戶線程。
當唯一運行的線程爲守護線程時,Java虛擬機退出。
該方法必須在線程開始前調用。
Thread.java中的相關代碼:

	public final void setDaemon(boolean on) {
    	// 檢查權限,是否允許訪問
        checkAccess();
        // 若線程活躍,即已經開始未結束,則拋出異常
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        // 設置標誌位
        daemon = on;
    }

22. isDaemon方法

判斷線程是否爲守護線程。
Thread.java中的相關代碼:

	public final boolean isDaemon() {
    	// 直接返回
        return daemon;
    }

23. toString方法

返回線程對應的字符串形式。
Thread.java中的相關代碼:

	public String toString() {
    	// 獲取線程組
        ThreadGroup group = getThreadGroup();
        // 若線程組存在
        if (group != null) {
            // 返回線程名,線程優先級,線程組名稱
            return "Thread[" + getName() + "," + getPriority() + "," +
                           group.getName() + "]";
        } else { // 若線程組不存在
            // 返回線程名,線程優先級
            return "Thread[" + getName() + "," + getPriority() + "," +
                            "" + "]";
        }
    }

24. getContextClassLoader方法

獲取線程的上下文類加載器。
Thread.java中的相關代碼:

	// 由於代碼中調用getCallerClass方法,所以需要加上該註解
	// 詳解在1)處
    @CallerSensitive
	public ClassLoader getContextClassLoader() {
    	// 若線程上下文類加載器爲空,則返回null
        if (contextClassLoader == null)
            return null;
        //獲取安全管理器
        SecurityManager sm = System.getSecurityManager();
        // 若開啓了安全管理器
        if (sm != null) {
            // 檢查類加載器的權限
            ClassLoader.checkClassLoaderPermission(contextClassLoader,
                                                   Reflection.getCallerClass());
        }
        // 返回上下文類加載器
        return contextClassLoader;
    }

1)CallerSensitive註解

      jvm的開發者認爲jdk內有一些方法是危險的,不希望開發者調用,因此將這些方法通過CallerSensitive註解修飾。
      所有內部調用getCallerClass方法的方法都必須使用@CallerSensitive進行註解,該方法用來獲取調用該方法的類。在獲取調用該方法的類時,會跳過調用鏈路上所有被@CallerSensitive直接修飾的方法所在的類,避免了多層反射調用時產生不安全的隱患。

25. setContextClassLoader方法

爲線程設置上下文類加載器。
Thread.java中的相關代碼:

	public void setContextClassLoader(ClassLoader cl) {
    	// 獲取安全管理器
        SecurityManager sm = System.getSecurityManager();
        // 若開啓了安全管理器
        if (sm != null) {
            // 檢查權限,是否允許設置上下文類加載器
            sm.checkPermission(new RuntimePermission("setContextClassLoader"));
        }
        // 保存到全局變量
        contextClassLoader = cl;
    }

26. holdsLock方法

判斷當前線程是否持有某個對象的鎖。
Thread.java中的相關代碼:

	public static native boolean holdsLock(Object obj);

27. getId方法

獲取線程ID。
Thread.java中的相關代碼:

    public long getId() {
        return tid;
	}

28. getState方法

獲取當前線程的狀態。
該方法用於監控系統狀態,而不是用於同步控制。
Thread.java中的相關代碼:

    public State getState() {
        return sun.misc.VM.toThreadState(threadStatus);
	}

29. yield方法

該方法用於提示線程調度程序,當前線程願意放棄當前處理器的使用。
該方法用來緩解線程對CPU的過度使用。
Thread.java中的相關代碼:

	public static native void yield();

30. sleep方法

當前正在執行的線程,在指定的時間內暫停執行。
線程不釋放持有的鎖。
Thread.java中的相關代碼:

    public static void sleep(long millis, int nanos)
	throws InterruptedException {
    	// 若毫秒小於0,則拋出異常
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        // 若納秒小於0或大於999999,則拋出異常
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        // 若納秒超過了500000,則化零爲整,毫秒加一
        // 若納秒不爲零且毫秒爲0,則設置最小時間1毫秒
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        // 調用重載方法
        sleep(millis);
    }

調用重載的sleep方法。
Thread.java中的相關代碼:

	public static native void sleep(long millis) throws InterruptedException;

31. stop方法

用於強制停止線程的執行。
棄用原因:線程在被停止時,停止的線程會突然釋放所有持有的鎖。之前等待這些鎖的對象,可能會產生不確定的行爲。
Thread.java中的相關代碼:

    // 該方法已被棄用,不建議使用
    @Deprecated
	public final void stop() {
    	// 獲取安全管理器
        SecurityManager security = System.getSecurityManager();
        // 若開啓了安全管理器
        if (security != null) {
            // 檢查權限,是否允許訪問
            checkAccess();
            // 若在一個線程中停止另一個線程
            if (this != Thread.currentThread()) {
                // 檢查權限
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }
        // 若線程的狀態不是新創建未運行的狀態
        if (threadStatus != 0) {
            // 若線程被掛起,喚醒線程
            resume(); 
        }

        // 停止線程運行
        // 詳解在1)處
        stop0(new ThreadDeath());
    }

1)stop0方法

停止線程的核心方法。
Thread.java中的相關代碼:

	private native void stop0(Object o);

32. suspend方法

暫停線程的執行,即將線程掛起。
若線程是活躍的,則將線程被掛起,直到線程被恢復,否則不會繼續執行。
棄用原因:容易造成死鎖。當線程被掛起時持有系統關鍵資源的鎖,則在它被恢復之前,其它線程不能訪問該資源。
Thread.java中的相關代碼:

    // 該方法已被棄用,不建議使用
    @Deprecated
	public final void suspend() {
    	// 檢查權限,是否允許訪問
        checkAccess();
        // 掛起線程
        // 詳解在1)處
        suspend0();
    }

1)suspend0方法

線程掛起的核心方法。
Thread.java中的相關代碼:

	private native void suspend0();

33. resume方法

恢復暫停(掛起)的線程。
棄用原因:此方法需要和suspend方法配合使用,因爲suspend方法易造成死鎖,被棄用,所以該方法也被棄用。
Thread.java中的相關代碼:

    // 該方法已被棄用,不建議使用
    @Deprecated
	public final void resume() {
    	// 檢查權限,是否允許訪問
        checkAccess();
        // 恢復線程
        // 詳解在1)處
        resume0();
    }

1)resume0方法

恢復掛起線程的核心方法。
Thread.java中的相關代碼:

	private native void resume0();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章