Я знаю, что notify()
- пробуждает любой один поток, а notifyAll()
- пробуждает все и даёт доступ одному. Но в чём отличие? в одних случаях работает notify()
, а в некоторых нет, но с notifyAll()
отлично. Как понять их?
There are two notification methods in the condition queue API —
notify
and notifyAll
. To call either, you must hold the lock
associated with the condition queue object. Calling notify
causes
the JVM to select one thread waiting on that condition queue to wake
up; calling notifyAll
wakes up all the threads waiting on that
condition queue. Because you must hold the lock on the condition queue
object when calling notify
or notifyAll
, and waiting threads
cannot return from wait without reacquiring the lock, the notifying
thread should release the lock quickly to ensure that the waiting
threads are unblocked as soon as possible.
Because multiple threads
could be waiting on the same condition queue for different condition
predicates, using notify
instead of notifyAll
can be dangerous,
primarily because single notification is prone to a problem akin to
missed signals.
© Brian Goetz "Java Concurrency in Practice"
Использование notify
потенциально более бережливо к ресурсам - не приходиться выводить потоки из спячки, не приходиться парковать их обратно, потокам не приходиться драться за блокировку и процессор в момент пробуждения. Но в некоторых ситуациях пробуждение только одного потока может приводить к потере сигнала и зависанию программы.
notify()
- нотифает только 1 поток, notifyAll()
- нотифает все потоки.
Может вы пробуждаете не тот поток, который вам нужен, а notifyAll()
пробуждает сразу все потоки.
Из вопроса на enSO:
Примером может служить набор потоков, ожидающих завершения
определенной задачи; как только задача будет завершена, все ожидающие
потоки могут продолжать свою деятельность. В таком случае вы будете
использовать notifyAll()
для одновременного пробуждения всех
ожидающих потоков.
Другой случай, например взаимоисключающая блокировка, только один из
ожидающих потоков может сделать что-то полезное после уведомления (в
этом случае получить блокировку). В таком случае вы предпочитаете
использовать notify()
.
Полезные различия:
Используйте notify()
, если все ваши ожидающие потоки взаимозаменяемы
(порядок, который они просыпают, не имеет значения), или если у вас
только один ожидающий поток. Общим примером является пул потоков,
используемый для выполнения заданий из очереди - при добавлении
задания один из потоков уведомляется о пробуждении, выполняет
следующее задание и возвращается в режим сна.
Используйте notifyAll()
для других случаев, когда потоки ожидания
могут иметь разные цели и должны иметь возможность запускать
одновременно. Примером может служить операция обслуживания совместно
используемого ресурса, где несколько потоков ждут завершения операции
перед доступом к ресурсу.
Если коротко и без занудства - notify
будит один какой то рандомный поток, notifyAll
- (внезапно
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Всем привет, подскажите пожалуйста, как можно cгенерировать POJO классы из схемы данных в виде файлаxml?
Имеется ArrayList вида String : intКак отсортировать его по возрастанию/убыванию по "колонке" int ?
Собственно говоря, сам вопрос кроется в залоговке данной темыЗнаю, что примерно с 2002 года освной реализацией JVM для платформы Java SE является...
У меня в папке webapp есть другая папка - static (webapp/static)В этой папке у меня лежат ресурсы: изображения, скрипты, каскадные стили