CodeGym /Java Blog /Toto sisi /Java 中的 Wait() 方法
John Squirrels
等級 41
San Francisco

Java 中的 Wait() 方法

在 Toto sisi 群組發布
在本文中,我們將了解用於控制線程的wait()方法,以及notify() / notifyAll()方法。這些方法在基類java.lang.Object中定義,因此,Java 中的繼承機制為所有類提供這些方法。也就是說,當您創建自己的類及其對象時,您始終可以調用這些方法。

wait() 和 notify()/notifyAll() 方法如何工作?

  • 等待()。簡而言之,此方法釋放監視器並將調用線程置於等待狀態,直到另一個線程調用 notify () / notifyAll()方法;
  • 通知()。繼續之前調用過 wait() 方法的線程的工作;
  • notifyAll()方法恢復之前調用過wait()方法的所有線程。
現在讓我們仔細看看wait()方法。Object類包含此方法的三個選項
  • public final native void wait(long timeoutMillis)拋出InterruptedException;它導致當前線程等待直到它被喚醒。通常它會在被通知或中斷時發生,或者直到經過一定的實時時間。

  • public final void wait()拋出InterruptedException。我們編寫了一個沒有參數的方法作為第二個方法並非巧合。事實上,如果你看一下它的代碼,它指的是方法的第一個變體,它只有 0L 參數。

  • public final wait (long timeout, int nanos)。導致當前線程等待直到它被喚醒,通常是通過被通知或中斷,或者直到一定量的實時已經過去。

wait ()方法旨在掛起調用線程。這是什麼意思?這些方法屬於類。基於類,您創建一個對象。對象存在於某些線程中。也就是說,對像是在一些線程中創建的。在這個對象工作的線程中,如果你在裡面調用wait(),就會導致這個線程停止。對象本身充當一種監視器。它是什麼?很明顯,您可以創建不同的對象,所有對像都將包含wait()方法。了解哪個對象導致特定線程停止。只要在參數中寫入,線程就會停止並等待。然後它就會開始。該線程無法自行啟動。要恢復工作,有 notify 和 notifyAll 方法。對notify()notifyAll() 的調用必須運行某個其他線程。使用wait(),您可以停止多個線程,並使用notifyAll()啟動所有線程。如果停止了多個線程並調用了notify(),則無法準確判斷哪個線程將恢復此方法。如果wait()方法上沒有等待線程,那麼當notify()notifyAll()被調用。線程只有在當前鎖定了特定對象時才能調用該對象的wait()notify()方法。wait()notify()notifyAll()只能從同步代碼中調用。

Wait() 方法示例

這裡我們有一個最流行的例子來說明該方法的工作原理。假設我們有一家商店、一個生產者和一個消費者。製造商將一些生產產品轉移到商店,之後消費者可以取走它們。讓製造商必須分別生產8種商品,消費者必須全部購買。但同時倉庫中最多只能有6件物品。為了解決這個問題,我們使用wait()notify()方法。讓我們定義三個類:MarketManufacturerClientrun()方法中的Manufacturer使用其8 種產品添加到Market對象放()方法。客戶端在run()方法中循環調用Market對象的get方法來獲取這些商品。Market類的 put 和 get 方法是同步的。為了跟踪商品在Market類中的存在,我們檢查 item 變量的值。獲取產品的 get() 方法只有在至少有一個產品時才會觸發因此,在 get 方法中,我們檢查產品是否丟失。如果該項目不可用,則調用wait()方法。該方法釋放Market對象的監視器並阻塞 get 方法,直到notify()在同一個監視器上調用方法。當在put()方法中添加一個項目並調用notify()時, get()方法獲取監視器。之後,我們的客戶收到一件物品。為此,將顯示一條消息,並減少該項目的值。最後,notify()方法調用向put()方法發出信號以繼續。在put()方法中,類似的邏輯起作用,只是現在如果Market中的產品不超過 6 個,put()方法應該起作用。

class Market {

   private int item = 0;

   public synchronized void get() {
       //here we use wait() method
       while (item < 1) {
           try {
               wait();
           }
           catch (InterruptedException e) {
           }
       }
       item--;
       System.out.println("A client has bought 1 item...");
       System.out.println("Items quantity in Market warehouse... " + item);
       notify();
   }

   public synchronized void put() {
       //here we use wait() method when the Warehouse is full
       while (item >= 6) {
           try {
               wait();
           }
           catch (InterruptedException e) {
           }
       }
       item ++;
       System.out.println("Manufacturer has added 1 more item...");
       System.out.println("Now there are " + item + " items in Warehouse" );
       notify();
   }
}

class Manufacturer implements Runnable {

   Market market;

   Manufacturer(Market market) {
       this.market = market;
   }


   public void run() {
       for (int i = 0; i < 8; i++) {
           market.put();
       }
   }
}

class Client implements Runnable {

   Market market;
   Client(Market market) {
       this.market = market;
   }
   public void run() {
       for (int i = 0; i < 8; i++) {
           market.get();
       }
   }
}
//wait() method test class
public class WaitTest {
   public static void main(String[] args) {

       Market market = new Market();
       Manufacturer manufacturer = new Manufacturer(market);
       Client client = new Client(market);
       new Thread(manufacturer).start();
       new Thread(client).start();
   }
}
在這裡,在get()方法中使用wait(),我們正在等待製造商添加新項目。而在添加之後,我們調用notify(),就好像說 Warehouse 上有一個地方空閒了你可以添加更多。在put()方法中,使用wait() ,我們正在等待Warehouse上的空間釋放。空間空閒後,我們添加項目,notify()啟動線程,客戶端可以拿起項目。這是我們程序的輸出:
製造商又添加了 1 件商品...現在倉庫裡有 1 件商品 製造商又添加了 1 件商品...現在倉庫裡有 2 件商品 製造商又添加了 1 件商品...現在倉庫裡有 3 件商品 製造商有添加了 1 個項目... 現在倉庫中有 4 個項目 製造商又添加了 1 個項目... 現在倉庫中有 5 個項目 製造商又添加了 1 個項目... 現在倉庫中有 6 個項目 客戶已購買1 件商品... 市場倉庫中的商品數量... 5 客戶購買了 1 件商品... 市場倉庫中的商品數量... 4 客戶購買了 1 件商品... 市場倉庫中的商品數量... 3客戶已購買 1 件商品... 市場倉庫中的商品數量... 2 客戶已購買 1 件商品... 市場倉庫中的商品數量... 1 客戶已購買 1 件商品... 市場倉庫中的商品數量...0 製造商又添加了 1 件商品... 現在倉庫中有 1 件商品 製造商又添加了 1 件商品... 現在倉庫中有 2 件商品 客戶購買了 1 件商品... 市場倉庫中的商品數量... 1 客戶購買了 1 件商品...市場倉庫中的商品數量...0 退出代碼為 0 的流程已完成
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION