乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Object類(lèi)wait,notify,notifyAll的使用

       9loong 2012-10-10

      這三個(gè)方法是java的基礎(chǔ)類(lèi)Object中定義的。

      Java所有的類(lèi)都具有線程的潛力,Java賦予的每個(gè)對(duì)象一個(gè)鎖,在計(jì)算機(jī)內(nèi)部工作在同一時(shí)間,只有一個(gè)對(duì)象可以持有鎖,也就是說(shuō)程序在同一時(shí)間只有一個(gè)程序可以運(yùn)行,這里我把對(duì)象比作是一個(gè)小的程序。而多處理器,那么就另當(dāng)別論了。

      在這里我們首先學(xué)習(xí)一下公共方法wait,notify,notifyAll。

      wait方法可以使在當(dāng)前線程的對(duì)象等待,直到別的線程調(diào)用此對(duì)象的notify或notifyAll方法(注意:調(diào)用的是此對(duì)象的notify和notifyAll),并且當(dāng)前運(yùn)行的線程必須具有此對(duì)象的對(duì)象監(jiān)視器,對(duì)象監(jiān)視器我們可以從三個(gè)方法中獲得,如下:

      1.在執(zhí)行對(duì)象實(shí)例同步方法體中,可以獲得此對(duì)象的對(duì)象監(jiān)視器,例子偽代碼如下:

      synchronized void aMethod(){

      while(condition)

      this.wait();

      //other mothed;
      }

      2.通過(guò)執(zhí)行對(duì)象同步synchronized正文,例子偽代碼如下:

      synchronized(this){

      while(condition)

      this.wait();

      //other mothed;
      }

      3.對(duì)于 Class 類(lèi)型的對(duì)象,可以通過(guò)執(zhí)行該類(lèi)的同步靜態(tài)方法

      這 個(gè)方法可以使當(dāng)前對(duì)象滿足條件condition后,執(zhí)行等待,當(dāng)前線程對(duì)象放棄鎖,cpu記錄當(dāng)前線程狀態(tài),以備下次回復(fù)。然后讓其他線程運(yùn)行,直到其 他線程調(diào)用此對(duì)象的notify或notifyAll方法,此對(duì)象才會(huì)重新獲得此對(duì)象的對(duì)象監(jiān)視器,此對(duì)象才能重新運(yùn)行。

      注意:調(diào)用這個(gè)方法,必須具有對(duì)象監(jiān)視器,也就是說(shuō)我們必須在這三種方法選一種來(lái)獲得對(duì)象監(jiān)視器,如果調(diào)用此方法wait,卻沒(méi)用對(duì)象監(jiān)視器,那么運(yùn)行時(shí)會(huì)拋出IllegalMonitorStateException.

      而且,在靜態(tài)方法中也無(wú)法獲得對(duì)象監(jiān)視器,只能在Class類(lèi)型的對(duì)象中,我們才可以通過(guò)調(diào)用該類(lèi)的同步靜態(tài)方法來(lái)獲得對(duì)象監(jiān)視器。

      wait()
      JDk文檔寫(xiě)道

      在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法前,導(dǎo)致當(dāng)前線程等待。換句話說(shuō),此方法的行為就好像它僅執(zhí)行 wait(0) 調(diào)用一樣。
      當(dāng)前線程必須擁有此對(duì)象監(jiān)視器 。該線程發(fā)布對(duì)此監(jiān)視器的所有權(quán)并等待,直到其他線程通過(guò)調(diào)用 notify 方法,或 notifyAll 方法通知在此對(duì)象的監(jiān)視器上等待的線程醒來(lái)。然后該線程將等到重新獲得對(duì)監(jiān)視器的所有權(quán)后才能繼續(xù)執(zhí)行。

      對(duì)于某一個(gè)參數(shù)的版本,實(shí)現(xiàn)中斷和虛假喚醒是可能的,而且此方法應(yīng)始終在循環(huán)中使用:

      synchronized (obj) {
      while (<condition does not hold>)
      obj.wait();
      ... // Perform action appropriate to condition
      }

      此方法只應(yīng)由作為此對(duì)象監(jiān)視器的所有者的線程來(lái)調(diào)用。

      拋出:
      IllegalMonitorStateException - 如果當(dāng)前線程不是此對(duì)象監(jiān)視器的所有者。
      InterruptedException - 如果在當(dāng)前線程等待通知之前或者正在等待通知時(shí),任何線程中斷了當(dāng)前線程。在拋出此異常時(shí),當(dāng)前線程的中斷狀態(tài) 被清除。
      對(duì)于紅色部分的內(nèi)容,個(gè)人曾一直都不是很理解,什么叫做擁有此對(duì)象的監(jiān)視器。下面我們看看代碼: 

       DateFormat format = new SimpleDateFormat("yyyy-MM-dd:hh:mm:ss");
      private String getTime(){
          return format.format(Calendar.getInstance().getTime());
      }
      private Object monitor = new Object();
          public void waitOnce(String thread, final long ms) {
          Thread waitThread = new Thread() {
              public void run() {
                  synchronized (monitor) {//獲得對(duì)象監(jiān)視器
                      try {
                          System.out.println("Thread "
                                  + Thread.currentThread().getName()
                                  + " Wait at " + getTime());
                          monitor.wait(ms);
                          System.out.println("Thread "
                                  + Thread.currentThread().getName()
                                  + " Waked at " + getTime());
                      } catch (InterruptedException e) {
                      }
                  }
              };
          };
          waitThread.setName(thread);
          waitThread.start();
      }

      如果我們?nèi)サ魋ynchronized(monitor) ,運(yùn)行則會(huì)出現(xiàn)異常IllegalMonitorStateException。

      WaitAndNotifyTest test = new WaitAndNotifyTest();
      test.waitOnce("1", Long.MAX_VALUE); 

      寫(xiě)道

      Exception in thread “1″ java.lang.IllegalMonitorStateException

      而加上以后就沒(méi)問(wèn)題了。因此個(gè)人覺(jué)得使用synchronized關(guān)鍵字鎖定對(duì)象,也就是獲得了對(duì)象的監(jiān)視器了。

      notify()
      JDK文檔 寫(xiě)道

      喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。如果所有線程都在此對(duì)象上等待,則會(huì)選擇喚醒其中一個(gè)線程 。選擇是任意性 的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程通過(guò)調(diào)用其中一個(gè) wait 方法,在對(duì)象的監(jiān)視器上等待。

      直到當(dāng)前線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程 。被喚醒的線程將以常規(guī)方式與在該對(duì)象上主動(dòng)同步的其他所有線程進(jìn)行競(jìng)爭(zhēng);例如,喚醒的線程在作為鎖定此對(duì)象的下一個(gè)線程方面沒(méi)有可靠的特權(quán)或劣勢(shì)。

      此方法只應(yīng)由作為此對(duì)象監(jiān)視器的所有者的線程來(lái)調(diào)用。通過(guò)以下三種方法之一,線程可以成為此對(duì)象監(jiān)視器的所有者:

      通過(guò)執(zhí)行此對(duì)象的同步實(shí)例方法。
      通過(guò)執(zhí)行在此對(duì)象上進(jìn)行同步的 synchronized 語(yǔ)句的正文。
      對(duì)于 Class 類(lèi)型的對(duì)象,可以通過(guò)執(zhí)行該類(lèi)的同步靜態(tài)方法。


      一次只能有一個(gè)線程擁有對(duì)象的監(jiān)視器。

      拋出:
      IllegalMonitorStateException – 如果當(dāng)前線程不是此對(duì)象監(jiān)視器的所有者。

      首先理解一下獲得對(duì)象的監(jiān)視器,簡(jiǎn)單的說(shuō)就是取得了當(dāng)前對(duì)象的“加鎖”使用權(quán),最簡(jiǎn)單的就是使用synchronized關(guān)鍵字。另外使用 synchronized修飾的方法也行。

      notify方法還有一個(gè)值得提出的是它會(huì)在當(dāng)前線程釋放了對(duì)象鎖以后隨機(jī)喚醒一個(gè)在該對(duì)象上等待的線程 。

      看看一個(gè)例子: 

      public void awakeAndWait(String thread, final long ms) {
          Thread notifyThread = new Thread() {
              public void run() {
                  synchronized (monitor) {
                      monitor.notify();
                      System.out.println("Thread "
                              + Thread.currentThread().getName() + " Notify at "
                              + getTime());
                      //保持了對(duì)象鎖的等待
                      try {
                          Thread.sleep(ms);
                      } catch (InterruptedException e) {
                      }
                  }
                  //釋放了對(duì)象鎖之后的等待
                  try {
                      Thread.sleep(ms);
                  } catch (InterruptedException e) {
                  }
              };
          };
          notifyThread.setName(thread);
          notifyThread.start();
      }

      這個(gè)方法會(huì)喚醒一個(gè)在對(duì)象上等待的線程,并在兩次sleep后退出,注意的是一個(gè)sleep是在對(duì)象鎖內(nèi),而另一次則是在釋放了對(duì)象鎖以后,這時(shí)候運(yùn)行上面2個(gè)方法得到: 

       WaitAndNotifyTest test = new WaitAndNotifyTest();
      test.waitOnce("1", Long.MAX_VALUE);// 在對(duì)象上等待無(wú)限長(zhǎng)
      test.waitOnce("2", Long.MAX_VALUE);// 在對(duì)象上等待無(wú)限長(zhǎng)
      test.waitOnce("3", Long.MAX_VALUE);// 在對(duì)象上等待無(wú)限長(zhǎng)
      try {// 延遲2s
          Thread.sleep(2000);
      } catch (InterruptedException e) {
      }
      // 在喚醒一個(gè)在對(duì)象上等待的線程,本身執(zhí)行時(shí)間4s,2s是在對(duì)象鎖內(nèi)
      //,2s是在釋放了對(duì)象鎖以后
      test.awakeAndWait("3", 2000); 

      執(zhí)行結(jié)果為:

      寫(xiě)道

      Thread 1 Wait at 2011-05-06:10:57:04
      Thread 2 Wait at 2011-05-06:10:57:04
      Thread 3 Wait at 2011-05-06:10:57:04
      Thread 3 Notify at 2011-05-06:10:57:06
      Thread 1 Waked at 2011-05-06:10:57:08

      2秒后喚醒了線程1,盡管它自己執(zhí)行花了4s,在釋放了對(duì)象鎖之后的2s不會(huì)影響線程1的執(zhí)行。

      notifyAll()
      JDK文檔 寫(xiě)道

      喚醒在此對(duì)象監(jiān)視器上等待的所有線程 。線程通過(guò)調(diào)用其中一個(gè) wait 方法,在對(duì)象的監(jiān)視器上等待。
      直到當(dāng)前線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。被喚醒的線程將以常規(guī)方式與在該對(duì)象上主動(dòng)同步的其他所有線程進(jìn)行競(jìng)爭(zhēng);例如,喚醒的線程在作為鎖定此對(duì)象的下一個(gè)線程方面沒(méi)有可靠的特權(quán)或劣勢(shì)。

      此方法只應(yīng)由作為此對(duì)象監(jiān)視器的所有者的線程來(lái)調(diào)用。有關(guān)線程能夠成為監(jiān)視器所有者的方法的描述,請(qǐng)參閱 notify 方法。

      拋出:
      IllegalMonitorStateException – 如果當(dāng)前線程不是此對(duì)象監(jiān)視器的所有者。

      與notify稍微有一點(diǎn)差別的是,它會(huì)喚醒所有的等待線程。

      public void awakeAll(String thread) {
          Thread notifyThread = new Thread() {
              public void run() {
                  synchronized (monitor) {
                      monitor.notifyAll();
                      System.out.println("Thread "
                              + Thread.currentThread().getName()
                              + " Notify all at " + getTime());
                  }
              };
          };
          notifyThread.setName(thread);
          notifyThread.start();
      }

      執(zhí)行一下代碼: 

       WaitAndNotifyTest test = new WaitAndNotifyTest();
      test.waitOnce("1", Long.MAX_VALUE);// 在對(duì)象上等待無(wú)限長(zhǎng)
      test.waitOnce("2", Long.MAX_VALUE);// 在對(duì)象上等待無(wú)限長(zhǎng)
      test.waitOnce("3", Long.MAX_VALUE);// 在對(duì)象上等待無(wú)限長(zhǎng)
      try {// 延遲2s
          Thread.sleep(2000);
      } catch (InterruptedException e) {
      }
      test.awakeAll("4"); 

      結(jié)果為:

      寫(xiě)道

      Thread 1 Wait at 2011-05-06:10:59:15
      Thread 3 Wait at 2011-05-06:10:59:15
      Thread 2 Wait at 2011-05-06:10:59:15
      Thread 4 Notify all at 2011-05-06:10:59:17
      Thread 2 Waked at 2011-05-06:10:59:17
      Thread 3 Waked at 2011-05-06:10:59:17
      Thread 1 Waked at 2011-05-06:10:59:17

      全部喚醒了。

      總結(jié)
      總結(jié)一下:大概有以下幾點(diǎn):

      1.wait(),notify(),notifyAll()都需要在擁有對(duì)象監(jiān)視器的前提下執(zhí)行,否則會(huì)出現(xiàn)異常IllegalMonitorStateException。
      2.多個(gè)線程可以同時(shí)在一個(gè)對(duì)象上等待。
      3.notify()將隨機(jī)喚醒一個(gè)在對(duì)象上等待的線程,沒(méi)有一個(gè)都沒(méi)有,則什么都不做。
      4.notify()喚醒的線程,將在notify()線程釋放了對(duì)象監(jiān)視器以后才執(zhí)行,并不是notify了以后馬上執(zhí)行。
      5.Object的這些方法與Thread的sleep、interrupt相差還是很遠(yuǎn)的,不要混為一談了。


      (###)

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類(lèi)似文章 更多