wait,notify,sleep,join這幾個(gè)方法很常用
wait,notify,sleep,join這幾個(gè)方法很常用,這里涉及到多線程和同步問(wèn)題,這里稍微解釋一下.
1.wait和notify
這兩個(gè)方法都是Object中的方法,放在一塊是因?yàn)樗麄冴P(guān)系非常密切.
wait就是等待這個(gè)對(duì)象的同步鎖,不過(guò)調(diào)用這個(gè)方法必須先獲得這個(gè)對(duì)象的同步鎖,就這一點(diǎn)很多人就搞暈了.
這里先解釋一下這兩個(gè)方法,然后給出一個(gè)小例子說(shuō)明.
wait:等待對(duì)象的同步鎖,需要獲得該對(duì)象的同步鎖才可以調(diào)用這個(gè)方法,否則后收到一個(gè)IllegalMonitorStateException,這個(gè)是運(yùn)行時(shí)異常.調(diào)用這個(gè)方法后,就放棄了這個(gè)同步鎖了.如果不帶參數(shù)的wait方法就只有等別人喚醒了,如果帶一個(gè)參數(shù)的
化就設(shè)置等待最長(zhǎng)時(shí)間,過(guò)了這個(gè)時(shí)間即使沒(méi)有人喚醒這個(gè)線程也不再等待了.
notify:喚醒在等待該對(duì)象同步鎖的線程(只喚醒一個(gè),如果有多個(gè)在等待),但是notifyAll可以喚醒所有等待的線程,注意喚醒的時(shí)在notify之前wait的線程,之后的沒(méi)有效果.
這里舉一個(gè)通俗的例子,兩個(gè)人共有一個(gè)衛(wèi)生間(每次只能一個(gè)人用),他們都要刷牙和方便,他們是這樣約定的,輪流用,第一個(gè)人先刷牙,然后第二個(gè)人刷牙...
class Syn
{
public static void main(String[] args) throws Exception
{
TwoPeople.ONE.start();
TwoPeople.TWO.start();
}
}
class TwoPeople extends Thread
{
private int i=0;
static Thread ONE=new TwoPeople(1);
static Thread TWO=new TwoPeople(2);
static Object washroom=new Object();
private TwoPeople(int i){this.i=i;}
public void run(){
synchronized(washroom){
try{
if(i==1){
brush(); //1
washroom.wait(); //2
release(); //6
washroom.notify(); //7
}
else{
brush(); //3
washroom.notify(); //4
washroom.wait(); //5
release(); //8
}
}catch(InterruptedException e){e.printStackTrace();}
}
}
private void brush() {
System.out.println("People "+i+" is brushing !");
try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
//延遲兩秒看效果
System.out.println("People "+i+" has burshed !");
}
private void release(){
System.out.println("People "+i+" is releasing !");
try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
//延遲兩秒看效果
System.out.println("People "+i+" has released !");
}
};
上面的代碼很簡(jiǎn)短,而且表明了執(zhí)行順序,至于join和sleep還是下次再討論吧.
wait,notify,sleep,join和線程同步問(wèn)題(續(xù))
昨天沒(méi)有時(shí)間寫完這篇,今天補(bǔ)上,前面只說(shuō)明了wait和notify這兩個(gè)方法,這里討論一下sleep和join,說(shuō)實(shí)在的這兩個(gè)方法比wait和notify簡(jiǎn)單的多.
http://blog.csdn.net/treeroot/archive/2004/11/10/175508.aspx
sleep:Thread的靜態(tài)方法,當(dāng)前線程休眠一段時(shí)間,時(shí)間到了再恢復(fù)可運(yùn)行狀態(tài),時(shí)間到了不一定就執(zhí)行吧,還得競(jìng)爭(zhēng)CPU呢.
join:這個(gè)方法其實(shí)就是特殊的wait,wait方法一般都需要?jiǎng)e人notify(當(dāng)然也可以設(shè)置超時(shí)),但是join方法就不需要?jiǎng)e人notify了,一直等到這個(gè)線程死亡(就相當(dāng)于這個(gè)線程臨時(shí)前告訴那些在等它的人:你們進(jìn)來(lái)吧!)
本人不是很會(huì)舉例子,還是兩個(gè)人公用一個(gè)衛(wèi)生間吧,這回不刷牙了,改洗澡吧,總不能兩個(gè)人同時(shí)洗澡吧!就算可以,這里假設(shè)不可以吧.情況時(shí)這樣的:A在洗澡,B要等。
第一種情況:
B很聰明的,A洗澡可能要20分鐘到1小時(shí),我就先睡10分鐘看看好了沒(méi)有,沒(méi)有好就再睡10分鐘,最多多等10分鐘而已吧.
class Syn
{
public static void main(String[] args) throws Exception
{
Thread a=new Bathing();
a.start();
//B
int time=0;
while(a.isAlive()){
Thread.sleep(10000);
time+=10;
System.out.println("B has waited "+time+" minutes");
}
System.out.println("B can bath now!");
}
}
class Bathing extends Thread
{
public void run(){
bathing();
}
private void bathing() {
System.out.println("A is bathing !");
try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}
//延遲20秒看效果
System.out.println("A has bathed !");
}
};
這里連同步都不需要,不過(guò)B可能需要多等一段時(shí)間,因?yàn)樗赡軇偤萌デ瞄TA還沒(méi)有洗完,于是他又去睡,結(jié)果剛睡下A就洗完了.
第二種情況:
B變得更加聰明了,這樣等我不是虧了,如果我10分鐘敲一次門,我可能要多等10分鐘,但是如果我每秒敲一次我也沒(méi)法睡呀,于是想了一個(gè)高招,裝了一個(gè)機(jī)關(guān),當(dāng)A出來(lái)的時(shí)候機(jī)關(guān)就會(huì)按響門鈴,這樣B就可以高枕無(wú)憂了。
class Syn
{
public static void main(String[] args) throws Exception
{
Thread a=new Bathing();
a.start();
//B
int time=0;
a.join();
System.out.println("B can bath now!");
}
}
class Bathing extends Thread
{
public void run(){
bathing();
}
private void bathing() {
System.out.println("A is bathing !");
try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}
//延遲20秒看效果
System.out.println("A has bathed !");
}
};
這樣只要A一洗完,B就會(huì)被喚醒,這里A并沒(méi)有去notify他,但是還是間接的通知了B,當(dāng)然這里也可以用wati和notify實(shí)現(xiàn),不過(guò)就顯得不好了。
class Syn
{
public static void main(String[] args) throws Exception
{
Thread a=new Bathing();
a.start();
//B
int time=0;
synchronized(a){a.wait();}
System.out.println("B can bath now!");
}
}
class Bathing extends Thread
{
public void run(){
synchronized(this){
bathing();
notify();
}
}
private void bathing() {
System.out.println("A is bathing !");
try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}
//延遲20秒看效果
System.out.println("A has bathed !");
}
};
對(duì)于一般的對(duì)象就要用wait和notify了,但是對(duì)于一個(gè)線程來(lái)說(shuō),join方法有時(shí)候更加方便。
posted on 2009-03-15 21:49 大魚 閱讀(241) 評(píng)論(0) 編輯 收藏 所屬分類: j2se