notify()
позволяет писать более эффективный код, чем notifyAll()
.
Рассмотрим следующий фрагмент кода, который выполняется из нескольких параллельных потоков:
synchronized(this) {
while(busy) // a loop is necessary here
wait();
busy = true;
}
...
synchronized(this) {
busy = false;
notifyAll();
}
Это можно сделать более эффективным, используя notify()
:
synchronized(this) {
if(busy) // replaced the loop with a condition which is evaluated only once
wait();
busy = true;
}
...
synchronized(this) {
busy = false;
notify();
}
В случае, если у вас большое количество потоков, или если условие цикла ожидания требует больших затрат, notify()
будет значительно быстрее, чем notifyAll()
. Например, если у вас 1000 потоков, 999 потоков будут пробуждены и оценены после первого notifyAll()
, затем 998, затем 997 и так далее. Напротив, с решением notify()
будет пробужден только один поток.
Используйте notifyAll()
, когда вам нужно выбрать, какой поток будет выполнять следующую работу:
synchronized(this) {
while(idx != last+1) // wait until it's my turn
wait();
}
...
synchronized(this) {
last = idx;
notifyAll();
}
Наконец, важно понимать, что в случае notifyAll()
код внутри synchronized
блоков, которые были разбужены, будет выполняться последовательно, а не все сразу. Допустим, в приведенном выше примере три потока ожидают, а четвертый поток вызывает notifyAll()
. Все три потока будут пробуждены, но только один начнет выполнение и проверит состояние цикла while
. Если условие true
, он снова вызовет wait()
, и только тогда второй поток начнет выполняться и проверит свое состояние цикла while
и т. Д.