Пример использования wait(), notify() и notifyAll() в Java.

Пример использования wait(), notify() и notifyAll() в Java.

Класс Object в Java содержит три final метода для взаимодействия потоков. Это методы wait(), notify() и notifyAll(). В этой статье мы расскажем что это за методы и как их эффективно использовать в многопоточных программах.

Поток, вызывающий эти методы на любом объекте, должен иметь так называемый монитор (механизм многопоточного доступа к объекту). Если же его нет, то будет брошено исключение java.lang.IllegalMonitorStateException.

Метод wait()

У метода wait() есть три вариации. Один метод wait() бесконечно ждет другой поток, пока не будет вызван метод notify() или notifyAll() на объекте. Другие две вариации метода wait() ставят текущий поток в ожидание на определенное время. По истечении этого времени поток просыпается и продолжает работу.

Метод notify()

Вызов метод notify() пробуждает только один поток, после чего этот поток начинает выполнение. Если объект ожидают несколько потоков, то метод notify() разбудит только один из них. Выбор потока зависит от системной реализации управления потоками.

Метод notifyAll()

Метод notifyAll() пробуждает все потоки, хотя в какой последовательности они будут пробуждаться зависит от реализации ОС.

Методы wait(), notify() и notifyAll(). Практика

Давайте на примере посмотрим использование методов wait(), notify() и notifyAll().

Ниже представлен Java Bean, на котором будут работать наши потоки:

Для начала напишем класс, который будет ожидать другие потоки, пока они не закончат выполнение. Назовем его Waiter. В этом классе будет находиться монитор на объекте Message, используя синхронизирующий блок.

Далее создадим класс Notifier, который будет обрабатывать объект Message, а затем вызвать метод notify, чтобы разбудить ожидающие объект Message потоки.

А теперь напишем тестовый класс, который будет создавать несколько потоков Waiter и Notifier.

Когда мы запустим эту программу, то в консоле увидим ход её выполнения, но она так и не закончит работу. Дело в том, что есть два потока, которые ожидают на объекте Message, а метод notify() разбудит только один из них — другой поток все еще ждет свое уведомление.

Результат выполнения с использованием метода notify():

А теперь закомментируем вызов notify() и раскомментируем вызов notifyAll() в классе Notifier. После этого запустите программу еще раз.

Результат выполнения с использованием метода notifyAll():

Как видно выше, после вызова notifyAll() все потоки отработали и программа завершила выполнение.

Следите за обновлениями раздела Многопоточность и параллелизм, и за другими статьями сайта Javadevblog.com.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *