1. 程式人生 > >執行緒的四種狀態以及wait和sleep的區別

執行緒的四種狀態以及wait和sleep的區別

一、執行緒的四種狀態

新建(new):處於該狀態的時間很短暫。已被分配了必須的系統資源,並執行了初始化。表示有資格獲得CPU時間。排程器可以把該執行緒變為runnable或者blocked狀態

就緒(Runnable):這種狀態下只要排程器把時間片分配給執行緒,執行緒就能執行。處在這種狀態就是可執行可不執行的狀態

阻塞(Bolocked):執行緒能夠執行,但有個條件阻止它的執行。當執行緒處於阻塞狀態時,排程器將會忽略執行緒,不會分配給執行緒任何CPU時間(例如sleep)。只有重新進入了就緒狀態,才有可能執行操作。

死亡(Dead):處於死亡狀態的執行緒講不再是可排程的,並且再也不會得到CPU時間。任務死亡的通常方式是從run()方法返回。

一個任務進入阻塞狀態,可能有如下原因:
1.sleep
2.wait(),知道執行緒得到了notify()或者notifyAll()訊息,執行緒才會進入就緒狀態。
3.任務在等待某個輸入/輸出完成
4.執行緒在試圖在某個物件上呼叫其同步控制方法,但是物件鎖不可用,因為另一個任務已經獲取了這個鎖。

二、wait和sleep的區別

1.wait和notify方法定義在Object類中,因此會被所有的類所繼承。 這些方法都是final的,即它們都是不能被重寫的,不能通過子類覆寫去改變它們的行為。 而sleep方法是在Thread類中是由native修飾的,本地方法。

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

 

2.當執行緒呼叫了wait()方法時,它會釋放掉物件的鎖。
另一個會導致執行緒暫停的方法:Thread.sleep(),它會導致執行緒睡眠指定的毫秒數,但執行緒在睡眠的過程中是不會釋放掉物件的鎖的。

3.正因為wait方法會釋放鎖,所以呼叫該方法時,當前的執行緒必須擁有當前物件的monitor,也即lock,就是鎖。要確保呼叫wait()方法的時候擁有鎖,即,wait()方法的呼叫必須放在synchronized方法或synchronized塊中。

順便說說notify(),notify()方法會喚醒一個等待當前物件的鎖的執行緒。 如果多個執行緒在等待,它們中的一個將會選擇被喚醒。這種選擇是隨意的,和具體實現有關。(執行緒等待一個物件的鎖是由於呼叫了wait方法中的一個)。

被喚醒的執行緒是不能被執行的,需要等到當前執行緒放棄這個物件的鎖。
被喚醒的執行緒將和其他執行緒以通常的方式進行競爭,來獲得物件的鎖。也就是說,被喚醒的執行緒並沒有什麼優先權,也沒有什麼劣勢,物件的下一個執行緒還是需要通過一般性的競爭。
且notify方法和wait一樣,是需要放在synchronized方法或synchronized塊中。