1. 程式人生 > >Java中wait和sleep方法的區別

Java中wait和sleep方法的區別

lee join 告訴 inter art 過程 lam 兩個 一次

1、兩者的區別

  • 這兩個方法來自不同的類分別是Thread和Object
  • 最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法(鎖代碼塊和方法鎖)。
  • wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep可以在任何地方使用(使用範圍)
  • sleep必須捕獲異常,而wait,notify和notifyAll不需要捕獲異常
  • sleep方法屬於Thread類中方法,表示讓一個線程進入睡眠狀態,等待一定的時間之後,自動醒來進入到可運行狀態,不會馬上進入運行狀態,因為線程調度機制恢復線程的運行也需要時間,一個線程對象調用了sleep方法之後,並不會釋放他所持有的所有對象鎖,所以也就不會影響其他進程對象的運行。但在sleep的過程中過程中有可能被其他對象調用它的interrupt(),產生InterruptedException異常,如果你的程序不捕獲這個異常,線程就會異常終止,進入TERMINATED狀態,如果你的程序捕獲了這個異常,那麽程序就會繼續執行catch語句塊(可能還有finally語句塊)以及以後的代碼。
  • 註意sleep()方法是一個靜態方法,也就是說他只對當前對象有效,通過t.sleep()讓t對象進入sleep,這樣的做法是錯誤的,它只會是使當前線程被sleep 而不是t線程
  • wait屬於Object的成員方法,一旦一個對象調用了wait方法,必須要采用notify()和notifyAll()方法喚醒該進程;如果線程擁有某個或某些對象的同步鎖,那麽在調用了wait()後,這個線程就會釋放它持有的所有同步資源,而不限於這個被調用了wait()方法的對象。wait()方法也同樣會在wait的過程中有可能被其他對象調用interrupt()方法而產生

如果線程A希望立即結束線程B,則可以對線程B對應的Thread實例調用interrupt方法。如果此刻線程B正在wait/sleep/join,則線程B會立刻拋出InterruptedException,在catch() {} 中直接return即可安全地結束線程。

需要註意的是,InterruptedException是線程自己從內部拋出的,並不是interrupt()方法拋出的。對某一線程調用interrupt()時,如果該線程正在執行普通的代碼,那麽該線程根本就不會拋出InterruptedException。但是,一旦該線程進入到wait()/sleep()/join()後,就會立刻拋出InterruptedException。

waite()和notify()因為會對對象的“鎖標誌”進行操作,所以它們必須在synchronized函數或synchronized block中進行調用。如果在non-synchronized函數或non-synchronizedblock中進行調用,雖然能編譯通過,但在運行時會發生illegalMonitorStateException的異常。

補充兩個重要的方法:yield()和join()

yield方法

暫停當前正在執行的線程對象。

yield()方法是停止當前線程,讓同等優先權的線程或更高優先級的線程有執行的機會。如果沒有的話,那麽yield()方法將不會起作用,並且由可執行狀態後馬上又被執行。

join方法是用於在某一個線程的執行過程中調用另一個線程執行,等到被調用的線程執行結束後,再繼續執行當前線程。如:t.join();//主要用於等待t線程運行結束,若無此句,main則會執行完畢,導致結果不可預測。

說一下為什麽使用wait()方法時,一般是需要while循環而不是if?

技術分享圖片
while(!執行條件) {
    wait();
}
....


if(!執行條件) {
    wait();
}
....
技術分享圖片

while會一直執行循環,直到條件滿足,執行條件才會繼續往下執行。if只會執行一次判斷條件,不滿足就會等待。這樣就會出現問題。

我們知道用notify() 和notifyAll()可以喚醒線程,一般我們常用的是notifyAll(),因為notify(),只會隨機喚醒一個睡眠線程,並不一定是我們想要喚醒的線程。如果使用的是notifyAll(),喚醒所有的線程,那你怎麽知道他想喚醒的是某個正在等待的wait()線程呢,如果用while()方法,就會再次判斷條件是不是成立,滿足執行條件了,就會接著執行,而if會直接喚醒wait()方法,繼續往下執行,根本不管這個notifyAll()是不是想喚醒的是自己還是別人,可能此時if的條件根本沒成立。

舉個例子:

while去水果店買蘋果,沒有了,然後while就和水果店老板說,有水果的時候通知我,我先回去了。if也去水果店買蘋果,沒有了,然後if就和水果店老板說,有水果的時候通知我,我先回去了。過一段時間,水果店老板發短信告訴while和if,有水果了,while去一看,水果店只是進了香蕉,並不是蘋果,所以不是想要的水果,於是回去繼續等水果店老板通知,而if根本就不看是不是自己想要的蘋果,直接就叫老板送10斤水果過來,這樣會導致你得到錯誤的結果。

參考文獻:

Java中wait 和sleep 方法比較

JAVA—sleep()和wait()的區別

java中的sleep()和wait()的區別

Java中wait和sleep方法的區別