Многопоточность

Как работают методы wait(), notify() и notifyAll()?


Методы `wait()` , `notify()` и `notifyAll()` являются частью механизма синхронизации потоков в Java и используются для обеспечения взаимодействия и синхронизации между потоками. 1. Метод `wait()` вызывается на объекте монитора внутри синхронизированного блока кода и заставляет текущий поток ожидать, пока другой поток не вызовет метод `notify()` или `notifyAll()` на том же объекте монитора. Когда это происходит, ожидающий поток просыпается и продолжает выполнение. Метод `wait()` может быть вызван с параметрами, такими как время ожидания или условие, которое должно быть выполнено перед продолжением выполнения. 2. Метод `notify()` используется для уведомления одного из ожидающих потоков, который был приостановлен с помощью метода `wait()` . Он выбирает один из ожидающих потоков и сообщает ему, что он может продолжить выполнение. Если есть несколько потоков, ожидающих на одном объекте монитора, то не гарантируется, какой именно поток будет уведомлен. 3. Метод `notifyAll()` уведомляет все ожидающие потоки, чтобы они продолжили выполнение. Все потоки будут разбужены, но только один из них получит доступ к объекту монитора и продолжит выполнение, остальные потоки будут продолжать ожидание. Важно отметить, что методы `wait()` , `notify()` и `notifyAll()` могут быть вызваны только внутри синхронизированного блока кода, используя монитор объекта. Это обеспечивает правильную синхронизацию и избегает состояния гонки (race condition) между потоками. Пример использования методов `wait()` , `notify()` и `notifyAll()` : class Message { private String content; private boolean empty = true; public synchronized String read() { while (empty) { try { wait(); // ожидание, если сообщение пусто } catch (InterruptedException e) { e.printStackTrace(); } } empty = true; notifyAll(); // уведомление других потоков return content; } public synchronized void write(String message) { while (!empty) { try { wait(); // ожидание, если сообщение не было прочитано } catch (InterruptedException e) { e.printStackTrace(); } } empty = false; this.content = message; notifyAll(); // уведомление других потоков } } public class WaitNotifyExample { public static void main(String[] args) { final Message message = new Message(); Thread writerThread = new Thread(() -> { String[] messages = {"Привет", "Как дела?", "Пока"}; for (String msg : messages) { message.write(msg); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } message.write("Завершение"); }); Thread readerThread = new Thread(() -> { while (!message.read().equals("Завершение")) { System.out.println(message.read()); } }); writerThread.start(); readerThread.start(); } } В этом примере у нас есть класс `Message` , который представляет сообщение, доступное для чтения и записи. Метод `read()` вызывается потоком-читателем, чтобы прочитать сообщение, и он ожидает, пока сообщение не будет записано методом `write()` . Метод `write()` вызывается потоком-писателем, чтобы записать новое сообщение, и он ожидает, пока сообщение не будет прочитано методом `read()` . Потоки-писатель и-читатель создаются и запускаются в методе `main()` . Поток-писатель записывает несколько сообщений со случайной задержкой, а поток-читатель читает их и выводит на экран. Таким образом, методы `wait()` , `notify()` и `notifyAll()` позволяют потокам синхронизировать свои действия и обеспечивают взаимодействие между ними.


Копировать ссылку