JAVA 並發編程-傳統線程同步通訊技術(四)

來源:互聯網
上載者:User

標籤:


首先介紹幾個概念:

 

wait()方法

 

  wait()方法使得當前線程必須要等待,等到另外一個線程調用notify()或者notifyAll()方法。 

  當前的線程必須擁有當前對象的monitor,也即lock,就是鎖。 

  線程調用wait()方法,釋放它對鎖的擁有權,然後等待另外的線程來通知它(通知的方式是notify()或者notifyAll()方法),這樣它才能重新獲得鎖的擁有權和恢複執行。 

  要確保調用wait()方法的時候擁有鎖,即,wait()方法的調用必須放在synchronized方法或synchronized塊中。

 

    與sleep比較:

 

     當線程調用了wait()方法時,它會釋放掉對象的鎖。 

     另一個會導致線程暫停方法:Thread.sleep(),它會導致線程睡眠指定的毫秒數,但線程在睡眠的過程中是不會釋放掉對象的鎖的。

 

notify()方法

 

  notify()方法會喚醒一個等待當前對象的鎖的線程。

  如果多個線程在等待,它們中的一個將會選擇被喚醒。這種選擇是隨意的,和具體實現有關。(線程等待一個對象的鎖是由於調用了wait方法中的一個)。

  被喚醒的線程是不能被執行的,需要等到當前線程放棄這個對象的鎖。

  被喚醒的線程將和其他線程以通常的方式進行競爭,來獲得對象的鎖。也就是說,被喚醒的線程並沒有什麼優先權,也沒有什麼劣勢,對象的下一個線程還是需要通過一般性的競爭。

  notify()方法應該是被擁有對象的鎖的線程所調用。

 

  換句話說,和wait()方法一樣,notify方法調用必須放在synchronized方法或synchronized塊中。

  wait()和notify()方法要求在調用時線程已經獲得了對象的鎖,因此對這兩個方法的調用需要放在synchronized方法或synchronized塊中。

 

線程同步通訊實現demo:

 

傳統線程同步通訊技術,子線程迴圈10次,接著主線程迴圈100次,又回到子線程迴圈10次,接著再回到主線程又迴圈100次,如此迴圈50次


public class TraditionalThreadCommunication {/** * @param args */public static void main(String[] args) {final Business business = new Business();//建立了一個線程,並啟動new Thread(new Runnable() {@Overridepublic void run() {for(int i=1;i<=50;i++){//business的子函數business.sub(i);}}}).start();//因為mian方法本身就佔用一個線程,所以主線程不需要再new Threadfor(int i=1;i<=50;i++){business.main(i);}}}  class Business {    private boolean bShouldSub = true;  //互斥對象為business,即在同一時刻只能訪問sub或main其中一個方法  public synchronized void sub(int i){  //當bShouldSub==false時等待  while(!bShouldSub){  try {//方法使當前線程主動釋放互斥鎖,並進入該互斥鎖的等待隊列。(也就是說,它使當前線程暫停執行,//等待其他線程執行notify()方法或者notifyall()方法後再繼續執行本線程。)this.wait();} catch (InterruptedException e) {e.printStackTrace();}  }  for(int j=1;j<=10;j++){System.out.println("sub thread sequence of " + j + ",loop of " + i);  }  bShouldSub = false;  //this代表什嗎?--代表Business  //喚醒下一個線程  //喚醒在此對象監視器上等待的單個線程。如果所有線程都在此對象上等待,則會選擇喚醒其中一個線程。  //選擇是任意性的,並在對實現做出決定時發生。  this.notify();  }    public synchronized void main(int i){    //當bShouldSub==true時等待  while(bShouldSub){  try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}  }for(int j=1;j<=100;j++){System.out.println("main thread sequence of " + j + ",loop of " + i);}bShouldSub = true;this.notify();  }  }


列印結果:





總結:

 

   

    wait()和notify()方法要求在調用時線程已經獲得了對象的鎖,因此對這兩個方法的調用需要放在synchronized方法或synchronized塊中。synchronized保證了main和sub兩個方法在同一時刻只能有一個在執行,那麼bShouldSub值就是在判斷該哪個方法執行。

 

    執行過程可能為:sub()方法先執行(當然也可能是main方法先執行,只是bShouldSub==true,則會的wait),bShouldSub==true,執行for迴圈,之後設定bShouldSub=false,並喚醒等待線程,這時可能還是執行sub()方法(被喚醒的線程並沒有什麼優先權,也沒有什麼劣勢,對象的下一個線程還是需要通過一般性的競爭),但此時bShouldSub==false,故執行while語句,wait,然後main()方法執行。




著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

JAVA 並發編程-傳統線程同步通訊技術(四)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.