wait()和sleep()的區別

—————————————————————————————————————————
這二者的施加者是有本質區別的
sleep()是讓某個線程暫停運行一段時間,其控制範圍是由當前線程決定,也就是說,在線程裏面決定.比如如說,我要作的事情是 "點火->燒水->煮麪",而當我點完火以後我不當即燒水,我要休息一段時間再燒.對於運行的主動權是由個人流程來控制.
 
而wait(),首先,這是由某個肯定的對象來調用的,將這個對象理解成一個傳話的人,當這我的在某個線程裏面說"暫停!",也是 thisOBJ.wait(),這裏的暫停是阻塞,仍是"點火->燒水->煮飯",thisOBJ就比如一個監督個人人站在我旁邊,原本該線 程應該執行1後執行2,再執行3,而在2處被那個對象喊暫停,那麼我就會一直等在這裏而不執行3,但正個流程並無結束,我一直想去煮飯,但還沒被容許, 直到那個對象在某個地方說"通知暫停的線程啓動!",也就是thisOBJ.notify()的時候,那麼我就能夠煮飯了,這個被暫停的線程就會從暫停處 繼續執行.
 
 
其實二者均可以讓線程暫停一段時間,可是本質的區別是一個線程的運行狀態控制,一個是線程之間的通信的問題
 
在java.lang.Thread類中,提供了sleep(),
而java.lang.Object類中提供了wait(), notify()和notifyAll()方法來操做線程
sleep()能夠將一個線程睡眠,參數能夠指定一個時間。
而wait()能夠將一個線程掛起,直到超時或者該線程被喚醒。
    wait有兩種形式wait()和wait(milliseconds).
 
—————————————————————————————————————————
sleep和wait的區別
  1,這兩個方法來自不一樣的類分別是Thread和Object
  2,最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其餘線程可使用同步控制塊或者方法。
  3,wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep能夠在
    任何地方使用
   synchronized(x){
      x.notify()
     //或者wait()
   }
   4,sleep必須捕獲異常,而wait,notify和notifyAll不須要捕獲異常
—————————————————————————————————————————
————————————————————————————————————————— 
sleep是線程類(Thread)的方法,致使此線程暫停執行指定時間,給執行機會給其餘線程,可是監控狀態依然保持,到時後會自動恢復。
調用sleep不會釋放對象鎖。 
sleep()使得一個進程進入睡眠狀態,可是線程所佔有的資源並無釋放。
好比,你在synchronized模塊(加函數鎖或者對象鎖)裏面調用了sleep(),雖然線程睡着了並且沒有使用資源,可是它依然保存着鎖,別的線程依然沒法調用相關的synchronized模塊。
sleep是Thread的靜態類方法,誰調用的誰去睡覺。
最主要是sleep方法沒有釋放鎖不出讓系統資源。
sleep(milliseconds)能夠用時間指定使它自動喚醒過來,若是時間不到只能調用interrupt()強行打斷。
Thread.sleep(0)的做用是「觸發操做系統馬上從新進行一次CPU競爭」。
 
—————————————————————————————————————————
wait是Object類的方法,對此對象調用wait方法致使本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)後本線程才進入對象鎖定池準備得到對象鎖進入運行狀態。
sleep來自Thread類,和wait來自Object類。
 
wait方法釋放了鎖,使得其餘線程可使用同步控制塊或者方法,wait是進入線程等待池等待,出讓系統資源,其餘線程能夠佔用CPU。通常wait不會加時間限制,由於若是wait線程的運行資源不夠,再出來也沒用,要等待其餘線程調用notify/notifyAll喚醒等待池中的全部線程,纔會進入就緒隊列等待OS分配系統資源。
 
notify喚醒在此對象監視器上等待的單個線程。若是全部線程都在此對象上等待,則會選擇喚醒其中一個線程。直到當前的線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。此方法只應由做爲此對象監視器的全部者的線程來調用。
 
調用對像wait方法後,當前線程釋放對象鎖,進入等待狀態.直到其餘線程(也只能是其餘線程)經過notify 方法,或 notifyAll.該線程從新得到對像鎖.
繼續執行,記得線程必須從新得到對像鎖才能繼續執行.由於synchronized代碼塊內沒有鎖是寸步不能走的。
 
"當前的線程必須擁有此對象監視器"與"此方法只應由做爲此對象監視器的全部者的線程來調用"說明wait方法與notify方法必須在同步塊內執行,即synchronized(obj以內).
 
使用範圍:wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep能夠在任何地方使用。
 
   synchronized(x){ 
      x.notify() 
     //或者wait() 
   }
 
—————————————————————————————————————————
【wait()和notify()內部機制】
wait(),notify(),notifyAll()不屬於Thread類,而是屬於Object基礎類,也就是說每一個對象都有wait(),notify(),notifyAll()的功能。
由於【每一個對象都有鎖】,鎖是每一個對象的基礎,固然操做鎖的方法也是最基礎了。
 
wait():
等待對象的同步鎖,須要得到該對象的同步鎖才能夠調用這個方法,不然編譯能夠經過,但運行時會收到一個異常:IllegalMonitorStateException。
調用任意對象的 wait() 方法致使該線程阻塞,該線程不可繼續執行,而且該對象上的鎖被釋放。
 
notify():
喚醒在等待該對象同步鎖的線程(只喚醒一個,若是有多個在等待),注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且不是按優先級。
調用任意對象的notify()方法則致使因調用該對象的 wait()方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到得到鎖後才真正可執行)。
 
notifyAll():
喚醒全部等待的線程,注意喚醒的是notify以前wait的線程,對於notify以後的wait線程是沒有效果的。
 
 —————————————————————————————————————————
【Java使用wait/notify  機制是爲了不輪詢帶來的性能損失,跟synchronized關鍵字比較有什麼好處呢?】
若使用簡單的synchonized機制實現互斥,會致使線程主動發起輪詢,若N次輪詢沒有成功,就產生了N次的CPU空間浪費;
若是加上了 wait/notify機制,就能夠避免這些無謂的輪詢,節省CPU的消耗。
 
一般,多線程之間須要協調工做。例如,瀏覽器的一個顯示圖片的線程displayThread想要執行顯示圖片的任務,必須等待下載線程 downloadThread將該圖片下載完畢。若是圖片尚未下載完,displayThread能夠暫停,當downloadThread完成了任務 後,再通知displayThread「圖片準備完畢,能夠顯示了」,這時,displayThread繼續執行。
以上邏輯簡單的說就是:若是【條件不知足,則等待】。當條件知足時,等待該條件的線程將被喚醒。
 
在Java中,這個機制的實現依賴於wait/notify。等待機制與鎖機制是密切關聯的。例如:
synchronized(obj) {while(!condition) {obj.wait();}obj.doSomething();}  
 
當線程A得到了obj鎖後,發現條件condition不知足,沒法繼續下一處理,因而線程A就wait()。
在另外一線程B中,若是B更改了某些條件,使得線程A的condition條件知足了,就能夠喚醒線程A:
synchronized(obj) {condition = true;obj.notify();} 
 
—————————————————————————————————————————
須要注意的概念是:
◆調用obj的wait(), notify()方法前,必須得到obj鎖,也就是必須寫在synchronized(obj) {...} 代碼段內。
◆調用obj.wait()後,線程A就釋放了obj的鎖,不然線程B沒法得到obj鎖,也就沒法在synchronized(obj) {...} 代碼段內喚醒A。
◆當obj.wait()方法返回後,線程A須要再次得到obj鎖,才能繼續執行。
◆若是A1,A2,A3都在obj.wait(),則B調用obj.notify()只能喚醒A1,A2,A3中的一個(具體哪個由JVM決定)。
◆obj.notifyAll()則能所有喚醒A1,A2,A3,可是要繼續執行obj.wait()的下一條語句,必須得到obj鎖,所以,A1,A2,A3只有一個有機會得到鎖繼續執行,例如A1,其他的須要等待A1釋放obj鎖以後才能繼續執行。
◆當B調用obj.notify/notifyAll的時候,B正持有obj鎖,所以,A1,A2,A3雖被喚醒,可是仍沒法得到obj鎖。直到B退出synchronized塊,釋放obj鎖後,A1,A2,A3中的一個纔有機會得到鎖繼續執行。
 
————————————————————————————————————————— 
相關文章
相關標籤/搜索