Два типичных примера.
Допустим, у вас есть поток производителя и поток потребителя. Каждый «пакет», произведенный производителем, должен быть потреблен потребителем. Потребитель помещает что-то в очередь, а затем вызывает notify ()
(для обработки одного «пакета» должен быть пропущен только один потребитель.)
Предположим, вы хотите получать уведомление, когда выполняется длительный процесс. закончил. Вам нужен звуковой сигнал и обновление экрана. Процесс выполняет notifyAll ()
, чтобы уведомить как поток звуковых сигналов, так и поток обновления экрана.
Разница в том, что notify()
стукет только по одному потоку, ожидающему текущего потока. Для большинства приложений производителя/потребителя и делегата и ожидания это правильный метод. Кроме того, если в текущем потоке ожидает только один другой поток, нет необходимости уведомлять больше, чем один ожидающий поток.
Напротив, notifyAll()
стучает all других потоков, ожидающих текущего потока. Это более полезно в ситуациях, когда каждый (связанный) спящий поток должен что-то сделать, например, в ответ на неустранимое или высоковажное событие, связанное с уведомляющим потоком.
Согласно JavaDoc для notify
:
Пробуждает единственный поток, ожидающий на мониторе этого объекта. Если какие-либо потоки ожидают этого объекта, один из них выбирается для пробуждения. Выбор произвольный и происходит по усмотрению реализации. Поток ожидает на мониторе объекта, вызывая один из методов ожидания.
Это может быть полезно, если у вас есть приложение, которое использует, например, очередь для размещения элементов, а затем имеет множество рабочих потоков, которые будут извлекать элементы из очереди. Когда элемент готов, вы можете вызвать notify
, чтобы разбудить одного рабочего для обработки элемента. По общему признанию, этот пример немного надуманный - вероятно, есть более эффективные способы реализовать это на Java, - но идею вы поняли.