Я предполагаю, что класс вверху - Q, в нем отсутствует какой-то код.В любом случае, общая идея заключается в том, что логические valueSet
и wait()
/ notify()
вызовы работают в тандеме.
Если потребитель уже начал ждать, он получил блокировку для экземпляра Q с помощью синхронизированного метода get()
, а затем снимает его, пока он ждет.
Если потребитель неНачав ждать, производитель может заблокировать экземпляр Q, так как метод put()
синхронизирован с той же блокировкой.Как только производитель выйдет из блокировки, он вызовет notify()
, а также установит логическое значение valueSet в значение true .
Следующий вызов потребителя get()
прочитает логическое значение прежде чем пытаться ждать , обратите внимание, что там что-то есть, возьмите содержимое n
и выполните любую необходимую работу.Если значение не было установлено, то есть ничего не произошло в отсутствие потребителя, он нажал бы wait()
на блокировку для новой работы, и следующий notify()
разбудит его.
Обновление
В вашем сценарии в комментариях вы, по сути, спрашиваете о точно такой же ситуации, но в обратном порядке.Та же логика применима.
В настоящее время потребитель ожидает, а производитель звонит notify()
.Производитель в настоящее время имеет блокировку и будет продолжать удерживать блокировку в течение всего метода.Все, что notify()
делает, это позволяет другому потоку, ожидающему в данный момент блокировки, знать, что, когда блокировка снята, она может попытаться снять блокировку и возобновить выполнение.В этом случае есть только один другой поток, но если бы было несколько потоков, он выбрал бы только один (чтобы разбудить всех, должен быть вызван notifyAll()
).
- Производитель выходит из метода, сняв блокировку.
- Потребитель просыпается и забирает блокировку.
На данный момент неясно, пришел ли уже производитель и ждет ли онзаблокировать или если он еще не вошел в метод.Тот же тандем логического флага и wait()
/ notify()
также применим к этому.
Прежде чем потребитель снимает блокировку, выйдя из метода, он установит для логического флага значение false и вызовет notify()
.
Если в данный момент производитель уже ожидает блокировки, вызов notify()
сообщит ему, что он может проснуться и продолжить работу после снятия блокировки.
Если производительне ожидает вызова wait()
, он должен находиться за пределами метода (возможно, ожидает входа в метод и получения блокировки таким образом).Когда потребитель выходит из метода и снимает блокировку, производитель получает его и проверяет логический флаг.Для него установлено значение false, поэтому производитель не пытается вызвать wait()
, а просто сбрасывает его значение, устанавливает логический флаг и вызывает notify()
.