← Назад к вопросам
В чем разница между методами 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() критично для успешного собеседования.