大魚

          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

          主站蜘蛛池模板: 新昌县| 托克逊县| 东明县| 额尔古纳市| 乐都县| 金川县| 台东市| 武鸣县| 黎川县| 开化县| 高唐县| 亚东县| 滦南县| 肇州县| 金坛市| 桑植县| 西华县| 新田县| 临颍县| 镇雄县| 绥江县| 大足县| 巫溪县| 淄博市| 长海县| 太谷县| 峨边| 米林县| 福安市| 奎屯市| 裕民县| 文成县| 堆龙德庆县| 安岳县| 广平县| 林州市| 红河县| 普安县| 深水埗区| 开封县| 济宁市|