wait 和notify 入門例子

2021-07-25 03:30:07 字數 3063 閱讀 7971

也就是說,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...