大魚

          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

          主站蜘蛛池模板: 钟祥市| 乡宁县| 象州县| 汉中市| 湖州市| 屏边| 龙川县| 黄石市| 乌鲁木齐市| 滁州市| 潞西市| 吴堡县| 太保市| 乌拉特前旗| 东乌| 大安市| 普兰店市| 满城县| 平安县| 天祝| 若尔盖县| 来宾市| 商河县| 顺平县| 大竹县| 株洲县| 敖汉旗| 贡山| 安义县| 泰安市| 龙井市| 南江县| 万荣县| 仁怀市| 北辰区| 集安市| 当涂县| 綦江县| 武山县| 盘锦市| 灵川县|