Java多線程狀態詳解以及sleep和wait的區別

對於線程的理解可以想象成每個人,就跟人一樣每個人都是有狀態的,比如這個人剛出生,剛睡醒,開始跑了,被綁住了,在等待,死亡都可以用來理解線程的狀態。


Java多線程狀態詳解以及sleep和wait的區別


一、線程的六種狀態

我們查看線程源碼會發現線程的六大狀態


  1. NEW 新建狀態,就是線程在start方法沒有執行前就屬於NEW狀態
  2. RUNNABLE 可以運行狀態,線程啟動了,等待CPU時間片的切換讓其運行,等待資源調度
  3. BLOCKED 阻塞狀態,使用synchronized或者lock時沒有獲得鎖時該線程就是鎖狀態
  4. WAITING 等待狀態,使用Thread.join()或者.wait()時,就進入了等待狀態
  5. TIMED_WAITING 計時等待,也就是說設定了等待時間,sleep(時間),join(時間),wait(時間)
  6. 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的區別


Java多線程狀態詳解以及sleep和wait的區別


  1. sleep和wait的顯著區別就是sleep不會釋放鎖而wait會釋放鎖。
  2. sleep可以在任何地方使用,wait,notify,notifyAll只能在同步控制方法或者同步控制塊使用

wati()和notify()可以用來幹嘛呢?簡單解釋就是每個對象都有wait方法,比如有一個用戶對象,然後有一個線程專門將用戶對象裡面的內容寫入到數據庫,這個用戶對象是由另一個線程不斷搜索查詢過來的,所以是不固定的,有時候user對象是有值的有時候沒有,如果我這個寫數據庫的線程每次都因為user對象沒有值還在不斷地運行那豈不是浪費資源碼?這時候就可以判斷後使用wait讓這個線程處於等待狀態,另一個線程將user信息寫入完成後在喚醒這個寫數據庫的線程,當然這種應用場景會很多,這裡只是簡單舉例。


Java多線程狀態詳解以及sleep和wait的區別


那sleep可以讓一個線程休眠從而讓出CPU資源取調度其他線程,不會釋放鎖,也就是其他線程不能調用被sleep的方法塊,除非sleep時間失效。

對於面試多線程也經常會問到sleep和wait的區別,如果不仔細研究的確會一臉懵逼,但確實有顯著差別

四、wait和notify以及notifyAll的聯繫


Java多線程狀態詳解以及sleep和wait的區別


wait是讓一個對象等待,notify就是將等待該對象的線程喚醒,notifyAll則是喚醒所有等待該對象的線程


分享到:


相關文章: