CodeGym /Blog Java /Random-PL /Metoda Wait() w Javie
Autor
Oleksandr Miadelets
Head of Developers Team at CodeGym

Metoda Wait() w Javie

Opublikowano w grupie Random-PL
W tym artykule przyjrzymy się metodzie wait() służącej do kontrolowania wątku oraz metodom notify() / notifyAll() . Metody te są zdefiniowane w klasie bazowej java.lang.Object i odpowiednio mechanizmy dziedziczenia, które są w Javie, zapewniają te metody absolutnie wszystkim klasom. Oznacza to, że kiedy tworzysz własną klasę i jej obiekty, zawsze możesz wywołać te metody.

Jak działają metody wait() i notify()/notifyAll()?

  • czekaj() . w skrócie, ta metoda zwalnia monitor i wprowadza wywołujący wątek w stan oczekiwania, aż inny wątek wywoła metodę notify() / notifyAll() ;
  • powiadomić() . Kontynuuje pracę wątku, którego metoda wait() została wcześniej wywołana;
  • notifyAll() wznawia wszystkie wątki, które wcześniej miały wywołaną metodę wait() .
Przyjrzyjmy się teraz bliżej metodzie wait() . Klasa Object zawiera trzy opcje dla tej metody:
  • public final native void wait(long timeoutMillis) zgłasza wyjątek InterruptedException ; Powoduje, że bieżący wątek czeka, aż zostanie przebudzony. Zwykle dzieje się to poprzez powiadomienie lub przerwanie lub do czasu, aż upłynie określony czas rzeczywisty.

  • public final void wait() zgłasza InterruptedException . To nie przypadek, że jako drugą napisaliśmy metodę bez parametrów. W rzeczywistości, jeśli spojrzysz na jego kod, odnosi się on do pierwszego wariantu metody, ma tylko argument 0L.

  • publiczne końcowe oczekiwanie (długi limit czasu, int nanos) . Powoduje, że bieżący wątek czeka, aż zostanie wybudzony, zwykle przez powiadomienie lub przerwanie, albo do upływu określonej ilości czasu rzeczywistego.

Metoda wait() ma na celu zawieszenie wywołującego wątku. Co to znaczy? Metody te należą do klasy. Na podstawie klasy tworzysz obiekt. W niektórych wątkach istnieją obiekty. Oznacza to, że obiekty są tworzone w niektórych wątkach. W wątku, w którym działa ten obiekt, jeśli wywołasz w nim funkcję wait() , doprowadzi to do tego, że ten wątek się zatrzyma. Sam obiekt pełni funkcję swego rodzaju monitora. Co to jest? Oczywiste jest, że możesz tworzyć różne obiekty i wszystkie z nich będą zawierać funkcję wait()metoda. Istnieje zrozumienie, który obiekt spowodował zatrzymanie określonego wątku. Wątek zatrzymuje się i będzie czekał tak długo, jak jest to zapisane w parametrze. A potem się zacznie. Ten wątek nie może się sam rozpocząć. Aby wznowić pracę, istnieją metody powiadamiania i powiadamiania Wszystkie. Wywołanie metody notify() lub notifyAll() musi odtwarzać inny wątek. Za pomocą wait() możesz zatrzymać wiele wątków i uruchomić wszystkie wątki za pomocą notifyAll() . Jeśli wiele wątków zostało zatrzymanych i wywołana została metoda notify() , nie można dokładnie określić, który wątek wznowi tę metodę. Jeśli w metodzie wait() nie ma oczekujących wątków , to nic się nie dzieje, gdy notify() lubPowiadomAll() jest wywoływana. Wątek może wywoływać metody wait() lub notify() na określonym obiekcie tylko wtedy, gdy aktualnie ma blokadę na ten obiekt. wait() , notify() i notifyAll() powinny być wywoływane tylko ze zsynchronizowanego kodu.

Przykład metody Wait().

Oto jeden z najpopularniejszych przykładów, który ilustruje działanie tej metody. Załóżmy, że mamy sklep, producenta i konsumenta. Producent przekazuje niektóre produkty produkcji do sklepu, po czym konsument może je odebrać. Niech producent musi wyprodukować odpowiednio 8 towarów, konsument musi je wszystkie kupić. Ale jednocześnie w magazynie nie może znajdować się więcej niż 6 pozycji w tym samym czasie. Aby rozwiązać ten problem, używamy metod wait() i notify() . Zdefiniujmy trzy klasy: Market , Manufacturer i Client . Producent w metodzie run() dodaje 8 produktów do obiektu Market za pomocą swojegometoda put() . Klient w metodzie run() w pętli wywołuje metodę get obiektu Market w celu pobrania tych produktów. Metody put i get klasy Market są zsynchronizowane. Aby śledzić obecność towaru w klasie Market sprawdzamy wartość zmiennej item. Metoda get() służąca do pobierania produktu powinna uruchamiać się tylko wtedy, gdy istnieje co najmniej jeden produkt. Dlatego w metodzie get sprawdzamy, czy brakuje produktu. Jeśli pozycja nie jest dostępna, wywoływana jest metoda wait() . Ta metoda zwalnia monitor obiektu Market i blokuje metodę get do momentu powiadomieniametoda jest wywoływana na tym samym monitorze. Gdy element zostanie dodany w metodzie put() i wywołana zostanie funkcja notify() , metoda get() pobiera monitor. Następnie nasz klient otrzymuje przedmiot. W tym celu wyświetlany jest komunikat, a wartość pozycji jest zmniejszana. Na koniec wywołanie metody notify() sygnalizuje metodzie put() kontynuację. W metodzie put() działa podobna logika, tylko teraz metoda put() powinna zadziałać jeśli na Rynku jest nie więcej niż 6 produktów .

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();
   }
}
Tutaj za pomocą wait() w metodzie get() czekamy aż Producent doda nową pozycję. A po dodaniu wywołujemy notify() , jakbyśmy chcieli powiedzieć, że zwolniło się jedno miejsce w Warehouse i można dodać więcej. W metodzie put() za pomocą wait() czekamy na zwolnienie miejsca na Warehouse . Po zwolnieniu miejsca dodajemy przedmiot, notify() uruchamia wątek i Klient może odebrać przedmiot. Oto wynik naszego programu:
Producent dodał jeszcze 1 element... Teraz w magazynie znajduje się 1 przedmiot Producent dodał jeszcze 1 element... Teraz w magazynie znajdują się 2 przedmioty Producent dodał jeszcze 1 element... Teraz w Magazynie znajdują się 3 przedmioty Producent dodał jeszcze 1 element... Teraz w Magazynie znajdują się 4 pozycje Producent dodał jeszcze 1 element... Teraz w Magazynie znajduje się 5 przedmiotów Producent dodał jeszcze 1 element... Obecnie w magazynie znajduje się 6 pozycji Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 5 Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 4 Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 3 Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 2 Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 1 Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 0 Producent dodał jeszcze 1 element... Teraz w magazynie znajduje się 1 przedmiot Producent dodał jeszcze 1 element... Teraz w magazynie znajdują się 2 przedmioty Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 1 Klient kupił 1 przedmiot... Ilość artykułów w magazynie Market... 0 Proces zakończył się kodem zakończenia 0
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION