對於線程的理解可以想象成每個人,就跟人一樣每個人都是有狀態的,比如這個人剛出生,剛睡醒,開始跑了,被綁住了,在等待,死亡都可以用來理解線程的狀態。
一、線程的六種狀態
我們查看線程源碼會發現線程的六大狀態
- NEW 新建狀態,就是線程在start方法沒有執行前就屬於NEW狀態
- RUNNABLE 可以運行狀態,線程啟動了,等待CPU時間片的切換讓其運行,等待資源調度
- BLOCKED 阻塞狀態,使用synchronized或者lock時沒有獲得鎖時該線程就是鎖狀態
- WAITING 等待狀態,使用Thread.join()或者.wait()時,就進入了等待狀態
- TIMED_WAITING 計時等待,也就是說設定了等待時間,sleep(時間),join(時間),wait(時間)
- TERMINATED 終止狀態,線程中斷或者停止運行的狀態
<code>public
class
Me
{
public
static
void
main
(String[] args
) { System.out
.println("hello world"
); } }/<code>
二、用代碼測試這些狀態是在什麼情況下發生的
我們使用代碼對線程的狀態進行一步步的監控,來更加深入的理解線程狀態的觸發方式,用休眠主線程的方式不斷地判斷子線程的狀態方式,對於wait()我們可以用一個新線程進行喚醒,這樣就可以順利進入到終止狀態,關於鎖狀態,這裡就沒演示了,可以用多個線程調用同一個方法實現這個鎖狀態。
<code>public
class
ThreadState
{public
static
void
main
(String[] args
) throws InterruptedException { ThreadState threadState=new
ThreadState(); Thread thread=new
Thread(()->{ synchronized (threadState){try
{for
(int
i=0
;i<10
;i++) {if
(i==0
){ Thread.sleep(1000
); }else
if
(i==1
){ threadState.wait(); }else
if
(i==2
){ System.out
.println("我復活了"
); } } }catch
(InterruptedException e) { e.printStackTrace(); } } }); Thread thread2=new
Thread(()->{ synchronized (threadState){ threadState.notify(); } }); System.out
.println("新建狀態:"
+thread.getState()); thread.start(); System.out
.println("等待運行狀態:"
+thread.getState()); Thread.sleep(500
); System.out
.println("計時等待狀態:"
+thread.getState()); Thread.sleep(1500
); System.out
.println("等待狀態:"
+thread.getState()); thread2.start(); Thread.sleep(1000
); System.out
.println("終止狀態:"
+thread.getState()); } }/<code>
輸出結果如下,可以清楚看到每種狀態的輸出結果
<code>新建狀態:NEW
等待運行狀態:RUNNABLE 計時等待狀態:TIMED_WAITING 等待狀態:WAITING 我復活了 終止狀態:TERMINATED/<code>
三、sleep和wait的區別
- sleep和wait的顯著區別就是sleep不會釋放鎖而wait會釋放鎖。
- sleep可以在任何地方使用,wait,notify,notifyAll只能在同步控制方法或者同步控制塊使用
wati()和notify()可以用來幹嘛呢?簡單解釋就是每個對象都有wait方法,比如有一個用戶對象,然後有一個線程專門將用戶對象裡面的內容寫入到數據庫,這個用戶對象是由另一個線程不斷搜索查詢過來的,所以是不固定的,有時候user對象是有值的有時候沒有,如果我這個寫數據庫的線程每次都因為user對象沒有值還在不斷地運行那豈不是浪費資源碼?這時候就可以判斷後使用wait讓這個線程處於等待狀態,另一個線程將user信息寫入完成後在喚醒這個寫數據庫的線程,當然這種應用場景會很多,這裡只是簡單舉例。
那sleep可以讓一個線程休眠從而讓出CPU資源取調度其他線程,不會釋放鎖,也就是其他線程不能調用被sleep的方法塊,除非sleep時間失效。
對於面試多線程也經常會問到sleep和wait的區別,如果不仔細研究的確會一臉懵逼,但確實有顯著差別
四、wait和notify以及notifyAll的聯繫
wait是讓一個對象等待,notify就是將等待該對象的線程喚醒,notifyAll則是喚醒所有等待該對象的線程