← Назад к вопросам

У какого класса есть метод notifyAll

2.3 Middle🔥 171 комментариев
#Многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Метод notifyAll в Java

Метод notifyAll() определён в классе java.lang.Object — самом базовом классе Java.

Сигнатура метода

public final void notifyAll()

Этот метод:

  • public — доступен всем
  • final — не переопределяется
  • void — ничего не возвращает
  • Определён в классе Object

Что делает notifyAll()

Метод notifyAll() пробуждает все потоки, которые ждут на мониторе (блокировке) данного объекта.

public class WaitNotifyExample {
    private static final Object lock = new Object();
    private static boolean ready = false;

    public static void main(String[] args) throws InterruptedException {
        // Поток 1 — ждёт
        Thread waiter = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Поток 1: начинаю ждать");
                    lock.wait(); // Ждёт уведомления
                    System.out.println("Поток 1: пробудился!");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        // Поток 2 — ждёт
        Thread waiter2 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Поток 2: начинаю ждать");
                    lock.wait(); // Ждёт уведомления
                    System.out.println("Поток 2: пробудился!");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        waiter.start();
        waiter2.start();

        Thread.sleep(1000);

        // Поток 3 — уведомляет ВСЕ потоки
        Thread notifier = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Поток 3: отправляю notifyAll()");
                lock.notifyAll(); // Пробудит ВСЕ ожидающие потоки
            }
        });

        notifier.start();
        notifier.join();
        waiter.join();
        waiter2.join();
    }
}

Вывод:

Поток 1: начинаю ждать
Поток 2: начинаю ждать
Поток 3: отправляю notifyAll()
Поток 1: пробудился!
Поток 2: пробудился!

notify() vs notifyAll()

notify() — пробуждает ОДИН поток

synchronized (lock) {
    lock.notify(); // Пробудит ОДНОГО из ожидающих
}

notifyAll() — пробуждает ВСЕ потоки

synchronized (lock) {
    lock.notifyAll(); // Пробудит ВСЕХ ожидающих
}

Требования к использованию

  1. Вызов ТОЛЬКО внутри synchronized блока:
// ✅ Правильно
synchronized (lock) {
    lock.notifyAll();
}

// ❌ Ошибка: IllegalMonitorStateException
lock.notifyAll(); // Без synchronized
  1. Поток должен владеть монитором объекта:
synchronized (obj) {
    // Текущий поток владеет монитором obj
    obj.notifyAll(); // OK
}

Когда использовать

notifyAll() используется в паттернах Producer-Consumer:

public class BlockingQueue<T> {
    private final Queue<T> queue = new LinkedList<>();
    private final int capacity;

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void put(T item) throws InterruptedException {
        while (queue.size() == capacity) {
            wait(); // Ждёт, если очередь полная
        }
        queue.add(item);
        notifyAll(); // Пробудит потребителей
    }

    public synchronized T take() throws InterruptedException {
        while (queue.isEmpty()) {
            wait(); // Ждёт, если очередь пустая
        }
        T item = queue.remove();
        notifyAll(); // Пробудит производителей
        return item;
    }
}

Современная альтернатива

Вместо wait()/notify() лучше использовать java.util.concurrent:

// Вместо synchronized + wait/notify
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();

public void waitForSignal() throws InterruptedException {
    lock.lock();
    try {
        condition.await();
    } finally {
        lock.unlock();
    }
}

public void signalWaiters() {
    lock.lock();
    try {
        condition.signalAll(); // Аналог notifyAll()
    } finally {
        lock.unlock();
    }
}

Вывод

notifyAll() — метод класса Object, используется для пробуждения всех потоков, ожидающих на мониторе. Требует вызова внутри synchronized блока. В современном коде рекомендуется использовать java.util.concurrent вместо wait/notify.