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

В чем разница между методами sleep() и wait()?

1.0 Junior🔥 111 комментариев
#Основы Java

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

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

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

Разница между sleep() и wait()

Это один из самых важных вопросов о многопоточности в Java. sleep() и wait() похожи по названию, но решают совершенно разные задачи и работают по-разному.

Thread.sleep()

Sleep замораживает поток на определённое время, но НЕ освобождает монитор (блокировку) объекта.

public class SleepExample {
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        synchronized (lock) {
            System.out.println("Нить заснула, но держит блокировку");
            Thread.sleep(2000); // поток спит 2 секунды
            System.out.println("Нить проснулась, блокировка всё ещё в руках");
        }
        // только здесь другие нити могут захватить lock
    }
}

Характеристики sleep():

  • Не освобождает монитор: поток держит захваченную блокировку
  • Статический метод: Thread.sleep(), вызывается на классе
  • Предсказуемое время: после указанного времени гарантированно пробуждается
  • Не требует синхронизации: может использоваться везде
  • InterruptedException: при прерывании выбрасывает исключение

Object.wait()

Wait отпускает монитор и ждёт, пока другая нить вызовет notify(). Это механизм для синхронизации нитей.

public class WaitExample {
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Нить 1: начало работы");
                try {
                    System.out.println("Нить 1: освобождаю монитор и жду");
                    lock.wait(); // отпускает блокировку, ждёт notify
                    System.out.println("Нить 1: проснулась после notify");
                } catch (InterruptedException e) {
                    System.err.println("Нить 1: прервана");
                }
            }
        });
        
        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(1000);
                synchronized (lock) {
                    System.out.println("Нить 2: пробуждаю ждущую нить");
                    lock.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
}

Характеристики wait():

  • Освобождает монитор: другие нити могут захватить блокировку
  • Метод объекта: вызывается на любом объекте (Object.wait())
  • Требует синхронизации: ТОЛЬКО внутри synchronized блока
  • Ждёт сигнала: не возвращается, пока notify() не будет вызван
  • InterruptedException: при прерывании выбрасывает исключение

Практический пример: Producer-Consumer

public class ProducerConsumerExample {
    static class Buffer {
        private Queue<Integer> queue = new LinkedList<>();
        private final int capacity = 5;
        
        public synchronized void produce(int value) throws InterruptedException {
            while (queue.size() == capacity) {
                System.out.println("Buffer полен, производитель ждёт...");
                wait(); // отпускает монитор, ждёт Consumer
            }
            queue.add(value);
            System.out.println("Производитель добавил: " + value);
            notifyAll(); // пробуждает Consumer
        }
        
        public synchronized int consume() throws InterruptedException {
            while (queue.isEmpty()) {
                System.out.println("Buffer пуст, потребитель ждёт...");
                wait(); // отпускает монитор, ждёт Producer
            }
            int value = queue.poll();
            System.out.println("Потребитель взял: " + value);
            notifyAll(); // пробуждает Producer
            return value;
        }
    }
}

Сравнительная таблица

Параметрsleep()wait()
Освобождает мониторНетДа
Где вызыватьВездеТолько в synchronized
ВызовThread.sleep()object.wait()
ПробуждениеПо времениnotify()/notifyAll()
ИспользованиеЗадержкиСинхронизация нитей
СтатическийДаНет

Частые ошибки

// ❌ ОШИБКА: вызов wait() вне synchronized
public void wrongWait() throws InterruptedException {
    object.wait(); // выбросит IllegalMonitorStateException
}

// ✅ ПРАВИЛЬНО
public synchronized void correctWait() throws InterruptedException {
    object.wait();
}

// ❌ ОШИБКА: ожидание одного notify при множестве нитей
lock.notify(); // может не пробудить нужную нить

// ✅ ПРАВИЛЬНО: используй notifyAll()
lock.notifyAll(); // пробудит все ждущие нити

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

sleep() — для простых задержек:

  • Тесты с паузами
  • Периодические задачи
  • Обратные отсчёты

wait() — для синхронизации нитей:

  • Producer-Consumer паттерны
  • Условные переменные
  • Ожидание событий от других нитей

В современной Java лучше использовать java.util.concurrent (Condition, Semaphore, CountDownLatch), но понимание sleep() и wait() критично для успешного собеседования.

В чем разница между методами sleep() и wait()? | PrepBro