JavaRush/Курсы/Модуль 2. Java Core/Знакомство с методами wait, notify, notifyAll

Знакомство с методами wait, notify, notifyAll

Открыта

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

— Привет, Риша!

— Я познакомлю тебя с методами wait, notify, notifyAll класса Object.

Сегодня мы просто ознакомимся с ними, но потом еще раз вернемся и уже выделим на это больше времени.

— Хорошо.

— Эти методы были придуманы как часть механизма синхронизации нитей.

Напомню, что в Java есть встроенный механизм управления доступом к общим ресурсам (объектам) из разных нитей. Нить может объявить какой-нибудь объект занятым, и другие нити будут вынуждены ждать, пока занятый объект не освободится.

— Я помню, это делается с помощью ключевого слова synchronized.

— Правильно. Обычно такой код выглядит примерно так:

public void print()
{
 Object monitor = getMonitor();
 synchronized(monitor)
 {
  System.out.println("text");
 }
}

Помнишь, как это работает?

— Ага. Если две нити одновременно вызовут метод print(), то одна из них войдет в блок, помеченный synchronized, и заблокирует monitor, поэтому вторая нить будет ждать, пока монитор не освободится.

— Правильно. Как только нить входит в блок, помеченный synchronized, то объект-монитор помечается как занятый, и другие нити будут вынуждены ждать освобождения объекта-монитора. Один и тот же объект-монитор может использоваться в различных частях программы.

— Кстати, почему – монитор?

— Монитором принято называть объект, который хранит состояние занят/свободен.

Вот тут и вступают в дело методы wait и notify.

Собственно, методов как таковых всего два. Остальные – это лишь модификации этих методов.

Теперь разберемся, что же такое метод wait и зачем он нужен.

Иногда в программе может оказаться такая ситуация, что нить вошла в блок кода synchronized, заблокировала монитор и не может работать дальше, т.к. каких-то данных еще не хватает: например, файл который она должна обработать еще не загрузился или что-нибудь в таком духе.

Мы же можем просто подождать, когда файл скачается. Можно просто в цикле проверять – если файл еще не скачался – спать, например, секунду и опять проверять и т.д.

Примерно так:

while(!file.isDownloaded())
{
 Thread.sleep(1000);
}
processFile(file);

Но в нашем случае такое ожидание слишком дорого. Т.к. наша нить заблокировала монитор, то другие нити вынуждены тоже ждать, хотя их данные для работы могут быть уже готовы.

Для решения этой проблемы и был придуман метод wait(). Вызов этого метода приводит к тому, что нить освобождает монитор и «становится на паузу».

Метод wait можно вызвать у объекта-монитора и только тогда, когда это монитор занят – т.е. внутри блока synchronized. При этом нить временно прекращает работу, а монитор освобождается, чтобы им могли воспользоваться другие нити.

Часто встречаются ситуации, когда в блок synchronized зашла нить, вызвала там wait, освободила монитор.

Затем туда вошла вторая нить и тоже стала на паузу, затем третья и так далее.

— А как же нить снимется с паузы?

— Для этого есть второй метод – notify.

Методы notify/notifyAll можно вызвать у объекта-монитора и только, когда этот монитор занят – т.е. внутри блока synchronized. Метод notifyAll снимает с паузы все нити, которые стали на паузу с помощью данного объекта-монитора.

Метод notify «размораживает» одну случайную нить, метод notifyAll – все «замороженные» нити данного монитора.

— Очень интересно, спасибо Риша.

— Рад, что тебе нравится, Амиго!

Есть еще модификации метода wait():

Метод wait() Пояснение
void wait(long timeout)
Нить «замерзает», но через переданное количество миллисекунд автоматически «размораживается».
void wait(long timeout, int nanos)
Нить «замерзает», но через переданное количество миллисекунд и наносекунд автоматически «размораживается».

Это, как еще говорят, wait с таймаутом. Метод работает как обычный wait, но если указанное время прошло, а нить никто не снял с паузы – она активируется сама.

Комментарии (22)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Underdante
Уровень 74
12 мая, 16:49
читаешь такои книгу ,а кто то пару глав вырвал.
Станислав
Уровень 2
2 октября 2025, 22:47
Вы тоже помните то, чего не было?)
Alexander
Уровень 115
30 сентября 2025, 17:06
ощущение что проспал половину лекции и теперь проснувшись, пытаешься понять, что происходит.
30 сентября 2025, 11:57
"Помнишь как это работает?" - ну да, конечно. Как можно помнить то, чего не было?!
Людмила
Уровень 115
29 сентября 2025, 10:12
После прочиения лекции по ссылке, стало немного легче читать про метод synchronized https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://javarush.com/groups/posts/1994-sinkhronizacija-potokov-operator-synchronized&ved=2ahUKEwjO88Ln1f2PAxVTAxAIHTUUOVgQFnoECBsQAQ&usg=AOvVaw0v8Ug4Bs4cEIEIfFx5drOu
Владимир
Уровень 40
1 августа 2025, 04:38
Структура курса утеряна - не ясно откуда до этого момента студенты должны знать про метод synchronized - он нигде не объяснялся. И стоит переименовать во всех лекция не понятные и никем не используемые "нити" в понятные и используемые всеми потоки.
Serge Menko Java Developer
21 ноября 2024, 13:37
а где раньше про synchronized рассказывали?оО
25 октября 2024, 09:42
Ну хоть бы переместили эту лекцию в уровень с нитями... Либо переписали так, чтобы все уровни подписок понимали её...
Артем Иевлев
Уровень 115
26 ноября 2024, 10:09
Не могу не согласиться
Булат
Уровень 111
28 сентября 2024, 13:52
как будто какую то часть лекции просто пропустили. что такое синхронизед?!, от слова совсем не понимейшн
Денис
Уровень 68
11 февраля 2025, 13:37
Абсолютли
Инна QA Automation Engineer
22 июня 2024, 07:58
такое ощущение, что мы пропустили разговоры Амиго и Риши про нити, которые они разговаривали без нас когда-то в прошлом)