Для чего нужен метод wait() в классе Object в Java?

«Для чего нужен метод wait() в классе Object в Java?» — вопрос из категории Java Core, который задают на 24% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Метод wait() — это основа механизма кооперативной синхронизации потоков (wait-notify). Он приостанавливает выполнение текущего потока до тех пор, пока другой поток не вызовет notify() или notifyAll() на том же объекте-мониторе.

Ключевые принципы:

  1. Вызов только в synchronized-блоке: wait(), notify(), notifyAll() можно вызывать только внутри критической секции, синхронизированной на том же объекте (this или явном lock).
  2. Освобождение монитора: При вызове wait() поток освобождает монитор, позволяя другим потокам войти в synchronized-секцию.
  3. Пробуждение и повторный захват: После вызова notify()/notifyAll() поток просыпается и пытается повторно захватить монитор, прежде чем продолжить выполнение.

Стандартный шаблон использования (идиома «охраняемого цикла»):

synchronized (sharedLock) {
    while (!condition) { // Всегда проверяйте условие в цикле!
        sharedLock.wait(); // Ждем, пока условие не станет true
    }
    // Выполняем работу, когда условие выполнено
    // ...
}
// В другом потоке:
synchronized (sharedLock) {
    condition = true;
    sharedLock.notifyAll(); // Пробуждаем все ожидающие потоки
}

Важные нюансы:

  • Spurious Wakeup: Поток может проснуться без вызова notify. Поэтому проверка условия всегда должна быть в цикле.
  • notify() vs notifyAll(): notify() будит один случайный поток, notifyAll() — все. Используйте notifyAll() для большей предсказуемости, если потоки ждут разных условий.
  • Применение: Реализация паттернов Producer-Consumer, пулов ресурсов, ограничителей (throttling) и других сценариев взаимодействия потоков.