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

Зачем нужен метод wait() из класса Object

1️⃣ Как кратко ответить

Метод wait() из класса Object используется для управления потоками в Java. Он заставляет текущий поток ожидать, пока другой поток не вызовет notify() или notifyAll() на том же объекте, чтобы синхронизировать выполнение потоков и избежать состояния гонки.

2️⃣ Подробное объяснение темы

В многопоточных приложениях часто возникает необходимость в координации работы нескольких потоков. Метод wait() из класса Object является ключевым инструментом для реализации этой координации. Он позволяет одному потоку приостановить выполнение и ждать, пока другой поток не выполнит определенное действие, например, не изменит состояние объекта, на котором вызван wait().

Как это работает

Когда поток вызывает wait() на объекте, он освобождает монитор этого объекта и переходит в состояние ожидания. Это означает, что другие потоки могут захватить монитор и выполнить свои задачи. Поток, вызвавший wait(), будет оставаться в состоянии ожидания до тех пор, пока другой поток не вызовет notify() или notifyAll() на том же объекте.

Пример использования

Рассмотрим пример, где один поток производит данные, а другой поток их потребляет. Мы хотим, чтобы поток-потребитель ждал, пока поток-производитель не произведет данные.

class Data {
    private String packet;
    private boolean transfer = true;
​
    public synchronized void send(String packet) {
        while (!transfer) {
            try {
                wait(); // Ожидание, пока данные не будут переданы
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Thread interrupted");
            }
        }
        transfer = false;
        this.packet = packet;
        notifyAll(); // Уведомление всех ожидающих потоков о том, что данные переданы
    }
​
    public synchronized String receive() {
        while (transfer) {
            try {
                wait(); // Ожидание, пока данные не будут получены
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Thread interrupted");
            }
        }
        transfer = true;
        notifyAll(); // Уведомление всех ожидающих потоков о том, что данные получены
        return packet;
    }
}

Объяснение кода

  • Класс Data: содержит данные, которые передаются между потоками.
  • Переменная transfer: флаг, указывающий, можно ли передавать данные. true означает, что данные могут быть переданы, false — что данные уже переданы и ожидают получения.
  • Метод send(String packet):
    • Синхронизирован, чтобы обеспечить доступ к данным только одним потоком в любой момент времени.
    • Использует цикл while, чтобы проверить состояние transfer. Если данные уже переданы, поток ждет.
    • wait() освобождает монитор и переводит поток в состояние ожидания.
    • После передачи данных устанавливает transfer в false и вызывает notifyAll(), чтобы разбудить все ожидающие потоки.
  • Метод receive():
    • Также синхронизирован.
    • Ждет, пока данные не будут готовы к получению.
    • После получения данных устанавливает transfer в true и вызывает notifyAll().

Зачем это нужно

Использование wait(), notify(), и notifyAll() позволяет избежать состояния гонки и гарантирует, что потоки будут корректно синхронизированы. Это особенно важно в системах, где потоки должны работать в строгой последовательности или когда один поток зависит от результата работы другого.

Тема: ООП
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки