原文:http://www.java67.com/2012/08/what-are-difference-between-wait-and.html
Wait vs sleep
在Java多線程面試里面,經常被問到wait() 和 sleep() 的區別。雖然 wait 和 sleep 都能將線程狀態變成等待狀態,但是它們在行為和使用方式上完全不一樣的。Thread.sleep(long millis) 會暫停、釋放CPU資源和給其他線程有執行的機會,而wait用于Java線程之間的通信。wait方法定義在java.lang.Object類里面,也就是說每個對象都能使用到。這是以對象鎖為基礎的,如果你記得在Java里面每一個對象都有隱藏鎖,也叫監視器(monitor)。當一個線程進入一個synchronized方法的時候它會獲得一個當前對象的鎖,而當進入的是靜態(static)的synchronized方法的時候獲得的是這個類的鎖。使用wait()和notify()這兩個方法可以使得兩個線程之間進行通信,這也是解決很多多線程問題的關鍵,比如生產者-消費者問題,哲學家就餐問題,讀和寫的問題和實現一些并發的設計。
在這個教程,你會學到下列關于wait()和sleep()方法的問題:
1、什么是wait()方法?
2、什么是sleep()方法?
3、它們之間有什么區別?
4、在什么地方使用到wait和sleep?
話說,如果你是在準備面試Java的話我建議你還是看一下Java Programming Interview Exposed,一本非常不錯的Java面試書籍。
Java里面的wait和sleep方法是什么
wait方法定義在Object類里面,所有對象都能用到,在線程通信中,wait()方法經常與notify()和notifyAll()方法一起使用。
當達到某種狀態的時候,wait()方法讓線程進入等待狀態,比如生產者-消費者問題中,當隊列滿了的時候,生產者這時候需要等待,同樣,當隊列空的時候,消費者也需要等待。
notify()方法用于喚醒正在等待的線程,這個線程即將停止等待的狀態,比如生產者線程往空隊列里面增加一個元素,此時notify方法會通知消費者線程這個隊列不再為空。另外,sleep()方法在Java應用中用于暫停線程。
當一個線程不用做其他事了,你可以調用sleep方法將線程睡眠,它會在一定時間內放棄當前的CPU資源。當一個線程已經是睡眠狀態的時候一段時間后它會正常的喚醒,也可以通過線程中斷的特殊方式將它喚醒。
Java線程中wait和sleep方法的區別
在最后一部分中我們可以看到什么是wait()和sleep()和它們之間的區別。正如我之前所說,除了等待之外,它們是完全不同的:
1)第一個很重要的區別就是,wait方法必須正在同步環境下使用,比如synchronized方法或者同步代碼塊。如果你不在同步條件下使用,會拋出IllegalMonitorStateException異常。另外,sleep方法不需要再同步條件下調用,你可以任意正常的使用。
2)第二個區別是,wait方法用于和定義于Object類的,而sleep方法操作于當前線程,定義在java.lang.Thread類里面。
3)第三個區別是,調用wait()的時候方法會釋放當前持有的鎖,而sleep方法不會釋放任何鎖。
4)wait方法最好在循環里面調用,是為了處理錯誤的通告,比如說,即使線程喚醒了,等待狀態仍然適用。(看不懂?大概是循環里面再判斷一次線程是否真的醒來),然而sleep方法沒這樣的限制。最好別在循環里面調用sleep方法。
下面是關于調用wait和sleep方法的代碼片段:
```
synchronized(monitor){
while(condition ==true){monitor.wait())//releases monitor lock
}
Thread.sleep(100);//puts current thread on Sleep
```
5)還有一個很大的區別是,一個是靜態方法,一個不是。
什么時候用wait和sleep方法?
從閱讀wait和sleep方法相關屬性和行為說明可以清楚的知道,wait()方法通常結合notify()或者notifyAll()方法在兩個線程通信中使用,而Thread.sleep()方法是個讓程序或者線程暫停的的工具方法。wait方法的調用需要同步環境這個必要條件才能進行,而sleep方法不需要。
完整的總結一下wait和sleep方法的區別和不同的使用場景。一般wait()和notify()方法使用于線程間的通信;sleep()方法用于暫停當前線程的執行。同時要注意,wait()方法會釋放鎖,而sleep()方法會一直持有鎖(直到睡眠結束)。所以如果你的設計中線程等待需要釋放鎖的話使用wait方法和nofity方法,否則使用sleep()方法.
結尾
第一次翻譯文章,翻譯有點生硬,望見諒,也歡迎指出翻譯不妥之處。