CodeGym/Java Blog/무작위의/Java의 Wait() 메서드
John Squirrels
레벨 41
San Francisco

Java의 Wait() 메서드

무작위의 그룹에 게시되었습니다
회원
이 기사에서는 스레드를 제어하는 ​​wait() 메서드와 notify() / notifyAll() 메서드를 살펴보겠습니다 . 이러한 메서드는 기본 클래스 java.lang.Object 에 정의되어 있으므로 Java의 상속 메커니즘은 절대적으로 모든 클래스에 이러한 메서드를 제공합니다. 즉, 고유한 클래스와 해당 개체를 만들 때 항상 이러한 메서드를 호출할 수 있습니다.

wait() 및 notify()/notifyAll() 메소드는 어떻게 작동합니까?

  • 대기() . 즉, 이 메서드는 모니터를 해제하고 다른 스레드가 notify () / notifyAll() 메서드를 호출할 때까지 호출 스레드를 대기 상태로 둡니다.
  • 알림() . wait() 메소드가 이전에 호출된 스레드의 작업을 계속합니다.
  • notifyAll() 메서드는 이전에 wait() 메서드를 호출한 모든 스레드를 재개합니다.
이제 wait() 메서드를 자세히 살펴보겠습니다 . Object 클래스 에는 이 방법에 대한 세 가지 옵션이 있습니다.
  • public final native void wait(long timeoutMillis) throws InterruptedException ; 현재 스레드가 깨어날 때까지 기다리게 합니다. 일반적으로 알림을 받거나 방해를 받거나 특정 실시간 시간이 경과할 때까지 발생합니다.

  • public final void wait() throws InterruptedException . 두 번째로 매개변수가 없는 메서드를 작성한 것은 우연이 아닙니다. 실제로 코드를 보면 메서드의 첫 번째 변형을 참조하며 0L 인수만 있습니다.

  • 공개 최종 대기 (긴 시간 초과, 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() 메서드를 사용합니다 . Market , ManufacturerClient 라는 세 가지 클래스를 정의해 보겠습니다 . run() 메서드 의 제조업체 는 다음을 사용하여 Market 개체 에 8개의 제품을 추가합니다.put() 메서드. 루프의 run() 메서드에 있는 클라이언트는 이러한 제품을 가져오기 위해 Market 개체 의 get 메서드를 호출합니다 . Market 클래스 의 put 및 get 메소드가 동기화됩니다. Market 클래스 에서 상품의 존재를 추적하기 위해 item 변수의 값을 확인합니다. 제품을 가져오기 위한 get () 메서드는 제품이 하나 이상 있는 경우에만 실행되어야 합니다. 따라서 get 메서드에서 제품이 누락되었는지 확인합니다. 항목을 사용할 수 없으면 wait() 메서드가 호출됩니다. 이 메서드는 Market 개체의 모니터를 해제 하고 notify()가 호출 될 때까지 get 메서드를 차단합니다.메서드가 동일한 모니터에서 호출됩니다. put() 메서드 에 항목을 추가 하고 notify()를 호출하면 get() 메서드가 모니터를 가져옵니다. 그 후 고객은 항목을 받습니다. 이를 위해 메시지가 표시되고 항목 값이 감소합니다. 마지막으로, notify() 메소드 호출은 put() 메소드에 계속하라는 신호를 보냅니다. put() 메서드 에서 유사한 논리가 작동하지만 이제 put() 메서드는 Market 에 제품이 6개 이하인 경우에만 작동합니다 .
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으로 완료되었습니다.
코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다