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() .
-
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.
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
GO TO FULL VERSION