JAVA線程狀態梳理以及Jstack命令使用

1.先上一張線程狀態轉換圖ide

clipboard.png

作以下說明:代碼中共有除RUNNING以外的6種狀態,爲了表示線程正在執行,特加了RUNNING這種狀態。咱們須要重點關注RUNNABLE、BLOCKED、WAITING和TIME_WAITING四種狀態,jstack打印的線程堆棧中也會時時出現。
1)BLOCKED:很好理解,就是線程在等待獲取鎖進入同步塊或者同步方法中。兩個死鎖的線程便是Blocked。
2)WAITING:比BLOCKED狀態進步一些,指我已經得到鎖了,但因爲有些條件不知足,我本身等會,調用object.wait()方法。等條件知足了,別的線程調用notify再叫我。另外也能夠調用Thread.join()方法,顧名思義就是調用別的線程的join方法,讓別人join進來先執行,那我就只能等會了。可是因爲wait()和notify()以及notifyAll()用於協調對共享資源的存取,因此必須在synchronized塊中使用。因此即使wait狀態的線程被notfiy喚醒了,也須要再次得到鎖,因此喚醒後進入Blocked狀態。
3)TIMED_WAITING:類比WAITING,差別是不須要notify()或者notifyAlL()方法喚醒,時間到了我本身醒了。另外sleep比較好理解,就是讓當前線程睡一會,與wait的區別是它不釋放鎖。
4)RUNNABLE不用多說,在JAVA虛擬機中已經在運行,可是在等待操做系統資源,好比CPU時間片。函數

2.模擬一段死循環代碼工具

public class NewTask2 implements Runnable{

    @Override
    public void run() {
        while(true)
        {
            System.out.println("the thread name is:" + Thread.currentThread().getName());
        }
    }

}

public class DemoApplication {

public static void main(String[] args) throws Exception {        
    Thread t = new Thread(new NewTask2());
    t.run();
}

}spa

3.運行main函數,查看任務管理器,找到PID,2284操作系統

clipboard.png

4.使用Process Explorer工具,找到2284進程並查看屬性。找到CPU佔用最高線程TID,8840線程

clipboard.png

5.將8840換算爲16進制,即爲2288,記下這個16進制數字code

6.在cmd下執行jstack -l PID命令,即jstack -l 2284。能夠看到nid=0x2288線程堆棧信息,線程狀態爲RUNNABLE和執行循環輸出的代碼行信息。另外也能夠看到WAITING狀態的線程進程

clipboard.png

clipboard.png

簡單梳理了下線程狀態轉移流程並記錄一下線程堆棧經常使用定位方法。ip