Ответ
notify() — это метод конечного (final) класса Object в Java, который используется для межпоточной синхронизации. Он пробуждает один произвольный поток, который находится в состоянии ожидания на том же самом мониторе (объекте), на котором был вызван notify().
Ключевые принципы:
- Работает только внутри синхронизированного блока: Метод
notify()должен вызываться из блока кода, защищенногоsynchronizedна том же объекте-мониторе, на котором потоки вызвалиwait(). - Не освобождает монитор: Вызов
notify()не приводит к немедленному освобождению монитора. Поток, вызвавшийnotify(), продолжает удерживать монитор до тех пор, пока не выйдет из своего синхронизированного блока (или метода). - Пробуждает один поток: Какой именно поток будет разбужен — зависит от реализации JVM, порядок не гарантируется.
- Без эффекта, если нет ожидающих: Если на момент вызова
notify()ни один поток не ожидает на этом мониторе (не вызвалwait()), то вызов игнорируется.
Пример (шаблон Producer-Consumer):
public class SharedResource {
private int value;
private boolean hasValue = false;
private final Object lock = new Object();
public void produce(int newValue) throws InterruptedException {
synchronized (lock) {
while (hasValue) { // Ожидание, если значение еще не потреблено
lock.wait();
}
value = newValue;
hasValue = true;
System.out.println("Produced: " + value);
lock.notify(); // Пробуждаем потребителя
}
}
public void consume() throws InterruptedException {
synchronized (lock) {
while (!hasValue) { // Ожидание, если значения нет
lock.wait();
}
System.out.println("Consumed: " + value);
hasValue = false;
lock.notify(); // Пробуждаем производителя
}
}
}
notify() vs notifyAll():
notify()— пробуждает один случайный поток из очереди ожидания. Эффективнее, но может привести к "голоданию" (starvation), если логика пробуждения неверна.notifyAll()— пробуждает все потоки, ожидающие на этом мониторе. Потоки по очереди повторно захватывают монитор и проверяют условие в циклеwhile. Более безопасный, но менее производительный вариант.
Важно: Использование wait()/notify() напрямую считается низкоуровневым и подверженным ошибкам. В современной разработке предпочтительнее использовать высокоуровневые конструкции из java.util.concurrent (например, BlockingQueue, Condition).