再談多線程的wait與notify和sleep

來源:互聯網
上載者:User

     在調用wait()之前,線程必須獲得該對象的對象層級鎖,即只能在同步方法或同步塊中調用wait()方法。在執行wait()方法後,當前線程釋放鎖,從wait()停止執行。在從wait()返回前,線程與其它線程競爭重新獲得鎖。如果調用wait()時沒有持有適當的鎖,則拋出IllegalMonitorStateException。


   方法notify()也要在同步方法或同步塊中調用,即在調用前,線程也必須獲得該對象的對象層級鎖。如果調用notify()時沒有持有適當的鎖,也會拋出IllegalMonitorStateException。該方法用來通知那些可能等待該對象的對象鎖的其它線程,如果有多個線程等待,則由線程規劃器隨機挑選出其中一個是wait狀態的線程,對其發出通知notify,並使它等待擷取該對象的對象鎖。需要說明的是,在執行notify()方法之後,當前線程不會馬上釋放該對象鎖,是wait狀態的線程也並不能馬上擷取該對象鎖,要等到執行notify()方法的線程將當前這次的語句程式執行完(如果notify在迴圈中的情況就會執行完當前這次迴圈語句塊中的語句再喚醒另外一個等待線程)當前線程才會釋放鎖,而wait狀態所在的線程才可以擷取該對象鎖。當第一個獲得該對象鎖的wait線程運行完畢之後,它會釋放掉該對象鎖,此時如果該對象沒有再次使用notify語句,則即便該對象已經空閑,其它wait狀態等待的線程由於沒有得到該對象的通知,還會繼續阻塞在wait狀態,直到這個對象發出一個notify或notifyAll。

紅色字型部分見程式碼分析與解析

package test;import java.util.ArrayList;import java.util.List;public class Test6{ private List<String>list=new ArrayList<String>(); public void add(){ list.add("草根"); }  public int size(){return list.size(); }  public static void main(String[] args) { final Test6 list=new Test6();  final Object lock=new Object();   Thread threadA=new Thread(){ public void run(){   try{  synchronized(lock){  if(list.size()!=5){  System.out.println("wait begin"+System.currentTimeMillis());  lock.wait();//wait()後面的語句都會停止執行釋放當前鎖  System.out.println("wait end"+System.currentTimeMillis());  }    }    }catch(Exception e){   }     }  }; threadA.start();   Thread threadB=new Thread(){ public void run(){   try{  synchronized(lock){ for(int i=0;i<10;i++){  list.add();  System.out.println("添加了"+(i+1)+"個元素");  if(list.size()==5){  lock.notify();//notify將會繼續執行完後面語句才會釋放當前鎖  System.out.println("我已經發出喚醒通知");  }  Thread.sleep(1000);  }    }    }catch(Exception e){      }       } }; threadB.start(); }}


sleep和wait的區別
   首先要明白多線程中鎖是對象層級的不是線程層級的,所以wait,notify,notifyall都只能在同步塊中對象(鎖)中調用,sleep線程對象(如Thread)調用
所以如果是調用Object中的方法wait方法那麼會導致阻塞,只有等待相應的對象調用了
   notify或者notifyall之後才會變為可運行態重新獲得CPU執行時間,如果是單調用sleep方法是對鎖沒有影響的,因為sleep是Thread中的,sleep方法調用不會釋放鎖,但是wait方法就會釋放鎖,但是wait和sleep都會導致線程暫停讓出CPU執行權,OS會重新分配給其它線程。


sleep 讓線程從 【running】 -> 【阻塞態】 時間結束/interrupt -> 【runnable】
wait 讓線程從 【running】 -> 【等待隊列】notify  -> 【鎖池】 -> 重新拿到鎖標識-》【runnable】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.