wait,notify,sleep,join這幾個方法很常用
wait,notify,sleep,join這幾個方法很常用,這里涉及到多線程和同步問題,這里稍微解釋一下.
1.wait和notify
這兩個方法都是Object中的方法,放在一塊是因為他們關系非常密切.
wait就是等待這個對象的同步鎖,不過調用這個方法必須先獲得這個對象的同步鎖,就這一點很多人就搞暈了.
這里先解釋一下這兩個方法,然后給出一個小例子說明.
wait:等待對象的同步鎖,需要獲得該對象的同步鎖才可以調用這個方法,否則后收到一個IllegalMonitorStateException,這個是運行時異常.調用這個方法后,就放棄了這個同步鎖了.如果不帶參數的wait方法就只有等別人喚醒了,如果帶一個參數的
化就設置等待最長時間,過了這個時間即使沒有人喚醒這個線程也不再等待了.
notify:喚醒在等待該對象同步鎖的線程(只喚醒一個,如果有多個在等待),但是notifyAll可以喚醒所有等待的線程,注意喚醒的時在notify之前wait的線程,之后的沒有效果.
這里舉一個通俗的例子,兩個人共有一個衛生間(每次只能一個人用),他們都要刷牙和方便,他們是這樣約定的,輪流用,第一個人先刷牙,然后第二個人刷牙...
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 !");
}
};
上面的代碼很簡短,而且表明了執行順序,至于join和sleep還是下次再討論吧.
wait,notify,sleep,join和線程同步問題(續)
昨天沒有時間寫完這篇,今天補上,前面只說明了wait和notify這兩個方法,這里討論一下sleep和join,說實在的這兩個方法比wait和notify簡單的多.
http://blog.csdn.net/treeroot/archive/2004/11/10/175508.aspx
sleep:Thread的靜態方法,當前線程休眠一段時間,時間到了再恢復可運行狀態,時間到了不一定就執行吧,還得競爭CPU呢.
join:這個方法其實就是特殊的wait,wait方法一般都需要別人notify(當然也可以設置超時),但是join方法就不需要別人notify了,一直等到這個線程死亡(就相當于這個線程臨時前告訴那些在等它的人:你們進來吧!)
本人不是很會舉例子,還是兩個人公用一個衛生間吧,這回不刷牙了,改洗澡吧,總不能兩個人同時洗澡吧!就算可以,這里假設不可以吧.情況時這樣的:A在洗澡,B要等。
第一種情況:
B很聰明的,A洗澡可能要20分鐘到1小時,我就先睡10分鐘看看好了沒有,沒有好就再睡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 !");
}
};
這里連同步都不需要,不過B可能需要多等一段時間,因為它可能剛好去敲門A還沒有洗完,于是他又去睡,結果剛睡下A就洗完了.
第二種情況:
B變得更加聰明了,這樣等我不是虧了,如果我10分鐘敲一次門,我可能要多等10分鐘,但是如果我每秒敲一次我也沒法睡呀,于是想了一個高招,裝了一個機關,當A出來的時候機關就會按響門鈴,這樣B就可以高枕無憂了。
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就會被喚醒,這里A并沒有去notify他,但是還是間接的通知了B,當然這里也可以用wati和notify實現,不過就顯得不好了。
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 !");
}
};
對于一般的對象就要用wait和notify了,但是對于一個線程來說,join方法有時候更加方便。
posted on 2009-03-15 21:49 大魚 閱讀(236) 評論(0) 編輯 收藏 所屬分類: j2se