JavaRush/Курсы/Модуль 2. Java Core/wait, notify, notifyAll ч.2

wait, notify, notifyAll ч.2

Открыта

— Привет, Амиго!

И еще пара деталей. Так сказать практических советов.

Пусть у тебя есть метод, который что-то ждет и засыпает, пока условие не выполнено.

Если коллекция пустая, то ждем
public synchronized Runnable getJob()
{
 if (jobs.size()==0)
  this.wait();

 return jobs.remove(0);
}

В документации по Java очень старательно советуют вызвать метод wait в цикле:

Если коллекция пустая, то ждем
public synchronized Runnable getJob()
{
 while (jobs.size()==0)
  this.wait();

 return jobs.remove(0);
}

Зачем это надо. Дело в том, что таких спящих нитей может быть два десятка. Разбудили всех, а задание забрать сможет только одна. Нить разбудили – но это еще не значит, что условие выполнилось!

Грубо говоря, могут быть «ложные побудки». Хороший разработчик должен учитывать это дело.

— Ясно. А не проще ли тогда использовать просто notify?

— А если в списке больше чем одно задание? Notify обычно советуют использовать ради оптимизации. Во всех остальных случаях рекомендуют использовать метод notifyAll.

— Ок.

— Но и это еще не все. Во-первых, может возникнуть ситуация, когда кто-то унаследовался от твоего класса, добавил туда свои методы и тоже использует wait/notifyAll. Т.е. может быть ситуация, когда на одном объекте висят независимые пары wait/notifyAll, которые друг о друге не знают. Поэтому что надо делать?

— Всегда вызывать wait в цикле и проверять, что условие выхода из цикла действительно выполнилось!

— Правильно. А чтобы тебе стало совсем понятно, что от этого никуда не деться, то многие разработчики указывают на то, что иногда нити просыпаются сами. Нити, которые гарантированно никто не может будить случайно. Похоже это побочный процесс оптимизации/ускорения кода в работающей Java-машине.

— Ничего себе. Понял, без цикла перед wait никуда.

Комментарии (6)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
КириллQA Engineer в Sogaz-OMS
22 января, 22:12
пу пу пу.....
Руслан
Уровень 48
20 октября 2025, 09:27
Очень интересные задачки !!
Артем
Уровень 56
Expert
16 мая 2024, 12:43
На мой взгляд правильное решение в задаче "Расставь wait-notify", не совсем правильное. А именно часть кода в классе MailServer.
synchronized (mail) {
       mail.wait();
 }
Так как метод wait должен вызваться в цикле, иначе есть шанс, что поток сам проснется, не дожидаясь вызова метода notify. (Согласно документации Oracle)
Misha Saharin
Уровень 111
Expert
4 ноября 2022, 13:46
в задаче "Расставь wait-notify" task2707 - синхронезить весь трай в обоих классах. под одним и тем же монитором, которым пользуются оба класса. wait & notify ставить по смыслу - ты догадаешься.
Greg
Уровень 108
Expert
20 октября 2022, 08:29
Ещё бы пару задачек сюда.
Александр Ц. System Engineer Expert
23 июня 2022, 12:13
Задача com.javarush.task.jdk13.task27.task2706. В методах run классов ConsumerTask и ProducerTask создай необходимые synchronized блоки. Валидатор принял без вышеуказанного условия. Возможно имелось в виду: в методах класса TransferObject проставь synchronized в нужные методы?