wait()方法使得當前線程必需要等待,等到另一個線程調用notify()或者notifyAll()方法。ide
當前的線程必須擁有當前對象的monitor,也即lock,就是鎖。this
線程調用wait()方法,釋放它對鎖的擁有權,而後等待另外的線程來通知它(通知的方式是notify()或者notifyAll()方法),spa
這樣它才能從新得到鎖的擁有權和恢復執行。.net
要確保調用wait()方法的時候擁有鎖,即,wait()方法的調用必須放在synchronized方法或synchronized塊中。線程
與sleep方法比較:對象
當線程調用了wait()方法時,它會釋放掉對象的鎖。blog
另外一個會致使線程暫停的方法:Thread.sleep(),它會致使線程睡眠指定的毫秒數,但線程在睡眠的過程當中是不會釋放掉對象的鎖的。繼承
notify()方法會喚醒一個等待當前對象的鎖的線程。ci
若是多個線程在等待,它們中的一個將會選擇被喚醒。這種選擇是隨意的,和具體實現有關。(線程等待一個對象的鎖是因爲調用了wait方法中的一個)。get
被喚醒的線程是不能被執行的,須要等到當前線程放棄這個對象的鎖。
被喚醒的線程將和其餘線程以一般的方式進行競爭,來得到對象的鎖。也就是說,被喚醒的線程並無什麼優先權,也沒有什麼劣勢,對象的下一個線程仍是須要經過通常性的競爭。
notify()方法應該是被擁有對象的鎖的線程所調用。
(This method should only be called by a thread that is the owner of this object's monitor.)
換句話說,和wait()方法同樣,notify方法調用必須放在synchronized方法或synchronized塊中。
wait()和notify()方法要求在調用時線程已經得到了對象的鎖,所以對這兩個方法的調用須要放在synchronized方法或synchronized塊中。
一個線程變爲一個對象的鎖的擁有者是經過下列三種方法:
1.執行這個對象的synchronized實例方法。
2.執行這個對象的synchronized語句塊。這個語句塊鎖的是這個對象。
3.對於Class類的對象,執行那個類的synchronized、static方法。
代碼示例:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
package
com.model.elgin.thread; public class TestThread6 { public static void main( String [] args) { final NumberExecute ne= new NumberExecute(); new Thread( new Runnable() { @Override public void run() { int i= 0 ; while (true) { ne.increase(); i++; if (i>= 100 ){ break ; } } } }).start(); new Thread( new Runnable() { @Override public void run() { int i= 0 ; while (true){ ne.decrease(); i++; if (i>= 100 ){ break ; } } } }).start(); } } class NumberExecute{ private int num; public synchronized void increase(){ while (num!= 0 ){ try { //若是num不爲0,當前線程等待。 wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println( "increase:" + num++); //喚醒在等待線程 notify(); } public synchronized void decrease(){ while (num== 0 ){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println( "decrease :" + num--); notify(); } } |
運行結果:
小結:
wait()和notify()方法要求在調用時線程已經得到了對象的鎖,所以對這兩個方法的調用須要放在synchronized方法或synchronized塊中。synchronized保證了increase和decrease兩個方法在同一時刻只能有一個在執行,那麼num的值就是在判斷該哪一個方法執行。
可能的執行過程:
首先初始的時候num=0 ,假設第一個線程先執行,不知足條件num!=0,故執行num+1,這是num變爲1,notify方法釋放鎖。
再次2個線程從新開始執行,依舊假設第一個先執行,知足num!=0,故執行wait方法將此線程阻塞,以後第二個線程執行,此時num=1,不知足num==0,故執行num--,以後num變爲0,並釋放鎖。以此反覆執行。