【java】Wait、Sleep、Yield

Java中wait、sleep的區別或者Java中sleep、yield的區別是Java面試或者多線程面試中最常問的問題之一。在這3個在Java中能夠用來暫停線程的方法中,sleep()和yield()方法是定義在Thread類中,而wait()方法是定義在Object類中的, 這也是面試中常問的一個問題。

wait()和sleep()的關鍵的區別在於,wait()是用於線程間通信的,而sleep()是用於短時間暫停當前線程。更加明顯的一個區別在於,當一個線程調用wait()方法的時候,會釋放它鎖持有的對象的管程和鎖,但是調用sleep()方法的時候,不會釋放他所持有的管程。

回到yield()方法上來,與wait()和sleep()方法有一些區別,它僅僅釋放線程所佔有的CPU資源,從而讓其他線程有機會運行,但是並不能保證某個特定的線程能夠獲得CPU資源。誰能獲得CPU完全取決於調度器,在有些情況下調用yield方法的線程甚至會再次得到CPU資源。所以,依賴於yield方法是不可靠的,它只能盡力而爲。

Wait vs Sleep vs Yield in Java

Java中wait和sleep的區別

wait和sleep的主要區別是調用wait方法時,線程在等待的時候會釋放掉它所獲得的monitor,但是調用Thread.sleep()方法時,線程在等待的時候仍然會持有monitor或者鎖。另外,Java中的wait方法應在同步代碼塊中調用,但是sleep方法不需要。
另一個區別是Thread.sleep()方法是一個靜態方法,作用在當前線程上;但是wait方法是一個實例方法,並且只能在其他線程調用本實例的notify()方法時被喚醒。另外,使用sleep方法時,被暫停的線程在被喚醒之後會立即進入就緒態(Runnable state),但是使用wait方法的時候,被暫停的線程會首先獲得鎖(譯者注:阻塞態),然後再進入就緒態。所以,根據你的需求,如果你需要暫定你的線程一段特定的時間就使用sleep()方法,如果你想要實現線程間通信就使用wait()方法。

下面列出Java中wait和sleep方法的區別:

  1. wait只能在同步(synchronize)環境中被調用,而sleep不需要。詳見Why to wait and notify needs to call from synchronized method
  2. 進入wait狀態的線程能夠被notify和notifyAll線程喚醒,但是進入sleeping狀態的線程不能被notify方法喚醒。
  3. wait通常有條件地執行,線程會一直處於wait狀態,直到某個條件變爲真。但是sleep僅僅讓你的線程進入睡眠狀態。
  4. wait方法在進入wait狀態的時候會釋放對象的鎖,但是sleep方法不會。
  5. wait方法是針對一個被同步代碼塊加鎖的對象,而sleep是針對一個線程。更詳細的講解可以參考《Java核心技術卷1》,裏面介紹瞭如何使用wait和notify方法。

yield和sleep的區別

yield和sleep的主要是,yield方法會臨時暫停當前正在執行的線程,來讓有同樣優先級的正在等待的線程有機會執行。如果沒有正在等待的線程,或者所有正在等待的線程的優先級都比較低,那麼該線程會繼續運行。執行了yield方法的線程什麼時候會繼續運行由線程調度器來決定,不同的廠商可能有不同的行爲。yield方法不保證當前的線程會暫停或者停止,但是可以保證當前線程在調用yield方法時會放棄CPU。
下面這張圖很好地展示了在調用wait、sleep、yield方法的時候,線程狀態如何轉換。


Java中sleep方法的幾個注意點:

  1. Thread.sleep()方法用來暫停線程的執行,將CPU放給線程調度器。
  2. Thread.sleep()方法是一個靜態方法,它暫停的是當前執行的線程。
  3. Java有兩種sleep方法,一個只有一個毫秒參數,另一個有毫秒和納秒兩個參數。
  4. 與wait方法不同,sleep方法不會釋放鎖
  5. 如果其他的線程中斷了一個休眠的線程,sleep方法會拋出Interrupted Exception。
  6. 休眠的線程在喚醒之後不保證能獲取到CPU,它會先進入就緒態,與其他線程競爭CPU。
  7. 有一個易錯的地方,當調用t.sleep()的時候,會暫停線程t。這是不對的,因爲Thread.sleep是一個靜態方法,它會使當前線程而不是線程t進入休眠狀態。

這就是java中的sleep方法。我們已經看到了java中sleep、wait以及yield方法的區別。總之,記住sleep和yield作用於當前線程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章