原文地址:Difference between Wait and Sleep, Yield in Java
Java中wait玄呛、sleep的區(qū)別或者Java中sleep、yield的區(qū)別是Java面試或者多線程面試中最常問的問題之一幌绍。在這3個在Java中能夠用來暫停線程的方法中,sleep()和yield()方法是定義在Thread類中故响,而wait()方法是定義在Object類中的傀广, 這也是面試中常問的一個問題。
wait()和sleep()的關(guān)鍵的區(qū)別在于彩届,wait()是用于線程間通信的伪冰,而sleep()是用于短時間暫停當(dāng)前線程。更加明顯的一個區(qū)別在于樟蠕,當(dāng)一個線程調(diào)用wait()方法的時候贮聂,會釋放它鎖持有的對象的管程和鎖靠柑,但是調(diào)用sleep()方法的時候,不會釋放他所持有的管程吓懈。
回到y(tǒng)ield()方法上來歼冰,與wait()和sleep()方法有一些區(qū)別,它僅僅釋放線程所占有的CPU資源耻警,從而讓其他線程有機(jī)會運行隔嫡,但是并不能保證某個特定的線程能夠獲得CPU資源。誰能獲得CPU完全取決于調(diào)度器甘穿,在有些情況下調(diào)用yield方法的線程甚至?xí)俅蔚玫紺PU資源腮恩。所以,依賴于yield方法是不可靠的温兼,它只能盡力而為秸滴。
Wait vs Sleep vs Yield in Java
Java中wait和sleep的區(qū)別
wait和sleep的主要區(qū)別是調(diào)用wait方法時,線程在等待的時候會釋放掉它所獲得的monitor募判,但是調(diào)用Thread.sleep()方法時荡含,線程在等待的時候仍然會持有monitor或者鎖。另外届垫,Java中的wait方法應(yīng)在同步代碼塊中調(diào)用内颗,但是sleep方法不需要。
另一個區(qū)別是Thread.sleep()方法是一個靜態(tài)方法敦腔,作用在當(dāng)前線程上均澳;但是wait方法是一個實例方法,并且只能在其他線程調(diào)用本實例的notify()方法時被喚醒符衔。另外找前,使用sleep方法時,被暫停的線程在被喚醒之后會立即進(jìn)入就緒態(tài)(Runnable state)判族,但是使用wait方法的時候躺盛,被暫停的線程會首先獲得鎖(譯者注:阻塞態(tài)),然后再進(jìn)入就緒態(tài)形帮。所以槽惫,根據(jù)你的需求,如果你需要暫定你的線程一段特定的時間就使用sleep()方法辩撑,如果你想要實現(xiàn)線程間通信就使用wait()方法界斜。
下面列出Java中wait和sleep方法的區(qū)別:
- wait只能在同步(synchronize)環(huán)境中被調(diào)用,而sleep不需要合冀。詳見Why to wait and notify needs to call from synchronized method
- 進(jìn)入wait狀態(tài)的線程能夠被notify和notifyAll線程喚醒各薇,但是進(jìn)入sleeping狀態(tài)的線程不能被notify方法喚醒。
- wait通常有條件地執(zhí)行君躺,線程會一直處于wait狀態(tài)峭判,直到某個條件變?yōu)檎婵小5莝leep僅僅讓你的線程進(jìn)入睡眠狀態(tài)。
- wait方法在進(jìn)入wait狀態(tài)的時候會釋放對象的鎖林螃,但是sleep方法不會奕删。
- wait方法是針對一個被同步代碼塊加鎖的對象,而sleep是針對一個線程疗认。更詳細(xì)的講解可以參考《Java核心技術(shù)卷1》急侥,里面介紹了如何使用wait和notify方法。
yield和sleep的區(qū)別
yield和sleep的主要是侮邀,yield方法會臨時暫停當(dāng)前正在執(zhí)行的線程,來讓有同樣優(yōu)先級的正在等待的線程有機(jī)會執(zhí)行贝润。如果沒有正在等待的線程绊茧,或者所有正在等待的線程的優(yōu)先級都比較低,那么該線程會繼續(xù)運行打掘。執(zhí)行了yield方法的線程什么時候會繼續(xù)運行由線程調(diào)度器來決定华畏,不同的廠商可能有不同的行為。yield方法不保證當(dāng)前的線程會暫妥鹨希或者停止亡笑,但是可以保證當(dāng)前線程在調(diào)用yield方法時會放棄CPU。
在Java中Sleep方法有兩個横朋, 一個只有一個毫秒?yún)?shù)仑乌,另一個有毫秒和納秒兩個參數(shù)。
sleep(long millis)
or
sleep(long millis, int nanos)
會讓當(dāng)前執(zhí)行的線程sleep指定的時間琴锭。
下面這張圖很好地展示了在調(diào)用wait晰甚、sleep、yield方法的時候决帖,線程狀態(tài)如何轉(zhuǎn)換厕九。
Java中sleep方法的幾個注意點:
- Thread.sleep()方法用來暫停線程的執(zhí)行,將CPU放給線程調(diào)度器地回。
- Thread.sleep()方法是一個靜態(tài)方法扁远,它暫停的是當(dāng)前執(zhí)行的線程。
- Java有兩種sleep方法刻像,一個只有一個毫秒?yún)?shù)畅买,另一個有毫秒和納秒兩個參數(shù)。
- 與wait方法不同细睡,sleep方法不會釋放鎖
- 如果其他的線程中斷了一個休眠的線程皮获,sleep方法會拋出Interrupted Exception。
- 休眠的線程在喚醒之后不保證能獲取到CPU纹冤,它會先進(jìn)入就緒態(tài)洒宝,與其他線程競爭CPU购公。
- 有一個易錯的地方,當(dāng)調(diào)用t.sleep()的時候雁歌,會暫停線程t宏浩。這是不對的,因為Thread.sleep是一個靜態(tài)方法靠瞎,它會使當(dāng)前線程而不是線程t進(jìn)入休眠狀態(tài)比庄。
這就是java中的sleep方法。我們已經(jīng)看到了java中sleep乏盐、wait以及yield方法的區(qū)別佳窑。總之父能,記住sleep和yield作用于當(dāng)前線程神凑。
感謝您的閱讀!
本賬號已經(jīng)不再更新何吝,更多文章請移步我的個人博客https://www.zacharyjia.me