В тази статия ще разгледаме метода wait() за управление на нишката и методите notify() / notifyAll() . Тези методи са дефинирани в базовия клас java.lang.Object и съответно механизмите за наследяване, които са в Java предоставят тези методи на абсолютно всички класове. Тоест, когато създавате свой собствен клас и неговите обекти, винаги можете да извиквате тези методи.
Как работят методите wait() и notify()/notifyAll()?
- изчакай() . накратко, този метод освобождава монитора и поставя извикващата нишка в състояние на изчакване, докато друга нишка извика метода notify() / notifyAll() ;
- notify() . Продължава работата на нишка, чийто метод wait() е бил извикан преди това;
- Методът notifyAll() възобновява всички нишки, които преди това са извикали своя метод wait() .
-
public final native void wait(long timeoutMillis) хвърля InterruptedException ; Това кара текущата нишка да изчака, докато се събуди. Обикновено това се случва, когато бъдете уведомени or прекъснати, or докато не изтече определено време в реално време.
-
public final void wait() хвърля InterruptedException . Неслучайно като втори написахме метод без параметри. Всъщност, ако погледнете неговия code, той се отнася до първия вариант на метода, има само аргумента 0L.
-
публично окончателно изчакване (дълъг период на изчакване, int nanos) . Кара текущата нишка да изчака, докато бъде събудена, обикновено чрез известяване or прекъсване, or докато не изтече определено време в реално време.
Пример за метод Wait().
Тук имаме един от най-популярните примери, който илюстрира How работи методът. Да кажем, че имаме магазин, производител и потребител. Производителят прехвърля някои продукти от производството в магазина, след което потребителят може да ги вземе. Нека производителят трябва да произведе 8 стоки, съответно потребителят трябва да ги купи всичките. Но в същото време не повече от 6 артикула могат да бъдат в склада едновременно. За да разрешим този проблем, използваме методите wait() и notify() . Нека дефинираме три класа: пазар , производител и клиент . Производителят в метода run() добавя 8 продукта към обекта Market , използвайки свояput() метод. Клиентът в метода run() в цикъл извиква метода get на обекта Market , за да получи тези продукти. Методите put и get на пазарния клас са синхронизирани. За да проследим наличието на стоки в пазарния клас, проверяваме стойността на променливата на артикула. Методът get() за получаване на продукт трябва да се активира само ако има поне един продукт. Следователно в метода get проверяваме дали продуктът липсва. Ако елементът не е наличен, се извиква методът wait() . Този метод освобождава монитора на обекта Market и блокира метода get, докато notify()методът се извиква на същия монитор. Когато се добави елемент в метода put() и се извика notify() , методът get() получава монитора. След това нашият клиент получава артикул. За да направите това, се показва съобщение и стойността на елемента се намалява. И накрая, извикването на метода notify() сигнализира на метода put() да продължи. В метода put() работи подобна логика, само че сега методът put() трябва да работи, ако няма повече от 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();
}
}
Тук, използвайки wait() в метода get() , ние чакаме производителя да добави нов артикул. И след като добавим, извикваме notify() , сякаш за да кажем, че едно място е станало свободно в Warehouse и можете да добавите още. В метода put() , използвайки wait() , ние чакаме освобождаването на място в Warehouse . След като мястото е свободно, добавяме артикула, notify() стартира нишката и клиентът може да вземе артикула. Ето резултата от нашата програма:
Производителят добави още 1 артикул... Сега има 1 артикула в склада Производителят добави още 1 артикул... Сега има 2 артикула в склада Производителят добави още 1 артикул... Сега има 3 артикула в склада Производителят има добави още 1 артикул... Сега има 4 артикула в склада. Производителят добави още 1 артикул... Сега има 5 артикула в склада. Производителят добави още 1 артикул... Сега има 6 артикула в склада. Клиент е купил 1 артикул... Количество артикули в склад Market... 5 Клиент е закупил 1 артикул... Количество артикули в склад Market... 4 Клиент е закупил 1 артикул... Количество артикули в склад Market... 3 Клиент е закупил 1 артикул... Количество артикули в склад на Market... 2 Клиент е закупил 1 артикул... Количество на артикули в склад на Market... 1 Клиент е закупил 1 артикул... Количество на артикули в склад на Market ...0 Производителят е добавил още 1 артикул... Сега има 1 артикула в склада Производителят е добавил още 1 артикул... Сега има 2 артикула в склада Клиент е закупил 1 артикул... Количество на артикулите в склада на Market... 1 Клиент е закупил 1 артикул... Количество на артикулите в склада на Market... 0 Процесът приключи с изходен code 0
GO TO FULL VERSION