也就是說,wait()會讓出物件鎖,同時,當前執行緒休眠,等待被喚醒,如果不被喚醒,就一直等在那兒。
notify()並不會讓當前執行緒休眠,但會喚醒休眠的執行緒。
先看第乙個例子!
public class threadf catch (interruptedexception e)
system.out.println("t1 end!");}}
};thread t2 = new thread() }};
t1.start();
t2.start();}}
這第乙個例子很簡單,寫了兩個執行緒(分別是兩個類,兩個run方法)。
兩個run方法之間沒有關係,但是,他們都用了同乙個object!
仔細看,t1裡面主要寫了個wait(),而t2裡面主要寫了個notify()。
我們看到執行結果是:
t1 start!
t2 start!
t2 end!
t1 end!
流程可以這樣解釋:
t1啟動,讓出鎖,讓出cpu,t2獲得cpu,啟動,喚醒使用了object的休眠的執行緒,t1被喚醒後等待啟動,t2繼續執行,t2執行完,t1獲得cpu後繼續執行。
值得一提的是,再強調一遍:
wait會讓出cpu而notify不會,notify重在於通知使用object的物件「我用完了!」,wait重在通知其它同用乙個object的執行緒「我暫時不用了」並且讓出cput。
所以說,看上面的順序,
t2 start!
t2 end!
是連續的,說明它並沒有因呼叫了notify而暫停!
那麼,如果兩個執行緒都寫wait沒有執行緒寫notify會有什麼現象呢?試一下就知道了。
結果是,
t1 start!
t2 start!
然後就是一直等待!
道理很顯然,t1先啟動,然後wait了,t2獲得了鎖和cpu,在沒有其它執行緒與它競爭的情況下,t2執行了,然後也wait了。
在這裡,兩個執行緒都在等待,沒有其它執行緒將它們notify,所以結果就是無休止地等下去!
至少說明了一點,wait後如果沒有其它執行緒將它notify,是絕不可能重新啟動的。不可能因為目前沒有執行緒占用cpu,某乙個正在等待的執行緒就自動重啟。
下面,我再把它改一下,寫四個執行緒,分別是
t1 wait()
t2 notify()
t3 notify()
t4 wait()
public class threadf catch (interruptedexception e)
system.out.println("t1 end!");}}
};thread t2 = new thread() }};
thread t3 = new thread() }};
thread t4 = new thread() catch (interruptedexception e)
system.out.println("t4 end!");}}
};t1.start();
t2.start();
t3.start();
t4.start();}}
首先,大家知道,執行緒啟動的順序,和**的先後順序,理論上是沒有關係的!
比如我這兒寫的是按t1-t2-t3-t4的先後順序先後start(),但實際上誰先啟動,是有一定機率的。
執行上面**,有兩種結果:
一種是剛好wait兩次,notify兩次,notify在wait之後執行,剛好執行完。
另一種是,也是剛好wait兩次,notify兩次,但是,notify在wait之前執行,於是,至少會有乙個執行緒由於後面沒有執行緒將它notify而無休止地等待下去!
我摘選了兩種情況的輸出結果,僅供參考:
1、可以執行結束的情況:
t1 start!
t2 start!
t2 end!
t1 end!
t4 start!
t3 start!
t3 end!
t4 end!
執行流程是:
t1啟動,wait,t2獲得鎖和cpu,t2宣布鎖用完了其它執行緒可以用了,然後繼續執行,t2執行完,t1被剛才t2喚醒後,等待t2執行完後,搶到了cpu,t1執行,
t1執行完,t4獲得cpu,啟動,wait,t3獲得了鎖和cpu,執行,宣布鎖用完了,其它執行緒可以用了,然後繼續執行,t3執行完,已經被喚醒並且等待已久的t4
得到cpu,執行。
2、不能執行結束,有執行緒由於沒有其它執行緒喚醒,一直在等待中:
t1 start!
t2 start!
t2 end!
t1 end!
t3 start!
t3 end!
t4 start!
執行流程:
t1啟動,wait,讓出cpu和鎖,t2得以啟動。t2啟動,並喚醒乙個執行緒,自己繼續執行。被喚醒的執行緒,也就是t1等待啟動機會。
t2執行完,t1搶到了cpu,執行,並結束。
這時,只剩下t3和t4,在此時,兩個執行緒的機會均等。
但是,t3搶到了cpu,於是它執行了,而且喚醒了執行緒,雖然此時並沒有執行緒休眠。說白了,它浪費了一次notify。t3順利執行完。
這時,終於輪到了t4,它啟動了,wait了,但是,後面已經沒有執行緒了,它的wait永遠不會有執行緒幫它notify了!
於是,它就這麼等著!
請仔細看執行流程,看懂,再自己做一下試驗。
仔看看,你會看到,凡是當前執行緒的run方法裡面寫了notify,有了start馬上就會end,而如果是寫的wait,有了start,下乙個絕對不是輸出這個執行緒的end。
所以說,t2和t3由於是寫的notify,它們的start和end總是成對出現。而t1和t4由於是寫的wait,它們start後,下乙個絕不可能是它的end。
最後再提醒一下,我們的wait和notify是針對同乙個object的,而非執行緒。我們這一篇都在講物件鎖,而不是執行緒。
順便說一下,如果沒有執行緒在wait,呼叫notify是不會有什麼問題的,就像這樣:
public class threadg }};
t1.start();}}
wait和notify造成死鎖的例子
public class threadlocktest implements runnable public static void main string args throws interruptedexception override public void run catch interru...
java高併發程式設計wait和 notify
wait和 notify必須配合synchronized使用 乙個執行緒修改乙個物件的值,而另乙個執行緒則感知到了變化,然後進行相應的操作,這就是wait notify 和notifyall 方法的本質。具體體現到方法上則是這樣的 乙個執行緒a呼叫了物件obj的wait方法進入到等待狀態,而另乙個執...
14 5 wait和notify方法 停止執行緒
wait 乙個執行緒如果執行了wait方法,那個該執行緒會進入乙個以鎖物件為識別符號的執行緒池中等待。等著中會釋放資源。notify 如果乙個執行緒開啟了notify方法,那麼久會喚醒以鎖物件為識別符號的執行緒中其中的乙個。notifyall 喚醒全部的執行緒。這個2個方法一定要用鎖物件來呼叫。st...