Что значит усыпить поток?
«Усыпить» поток означает приостановить его выполнение на заданный промежуток времени с помощью статического метода Thread.sleep(). Поток переходит из состояния RUNNABLE в состояние TIMED_WAITING и не потребляет процессорное время до истечения указанного интервала.
Сигнатуры метода
Пример
// Пауза на указанное число миллисекунд
public static void sleep(long millis) throws InterruptedException;
// Пауза с точностью до наносекунд
public static void sleep(long millis, int nanos) throws InterruptedException;
// Java 19+ — пауза с использованием Duration
public static void sleep(Duration duration) throws InterruptedException;
Ключевые особенности
| Аспект | Описание |
|---|---|
| Монитор | Поток не освобождает захваченные мониторы во время сна |
| Прерывание | Если во время сна вызван interrupt(), поток проснётся досрочно и выбросит InterruptedException. Флаг прерывания при этом сбрасывается |
| Точность | Реальная пауза может быть длиннее заданной (зависит от загрузки системы и гранулярности таймера ОС). На Windows гранулярность по умолчанию ~15.6 мс |
sleep(0) |
Отдаёт остаток текущего кванта времени планировщику, аналогично Thread.yield(), но с некоторыми отличиями |
Пример
Пример: усыпление с обработкой прерывания
public class SleepDemo {
public static void main(String[] args) {
Thread worker = new Thread(() -> {
try {
System.out.println("Поток засыпает на 5 секунд...");
Thread.sleep(5000);
System.out.println("Поток проснулся!");
} catch (InterruptedException e) {
System.out.println("Поток разбужен досрочно прерыванием!");
// Хорошая практика: восстановить флаг прерывания
Thread.currentThread().interrupt();
}
});
worker.start();
// Через 2 секунды прерываем спящий поток
try { Thread.sleep(2000); } catch (InterruptedException e) { }
worker.interrupt(); // Поток проснётся досрочно
}
}
Отличие от wait()
| Характеристика | Thread.sleep() |
Object.wait() |
|---|---|---|
| Освобождает монитор | Нет | Да |
Требует synchronized |
Нет | Да |
| Пробуждение | Только по таймеру или interrupt() |
По notify()/notifyAll(), таймеру или interrupt() |
| Назначение | Пауза на фиксированное время | Ожидание условия от другого потока |
Аналогия из жизни.
Thread.sleep()– это будильник: вы засыпаете и просыпаетесь через заданное время. Но если вас разбудят раньше (прерывание), вы проснётесь, но будете раздражены (InterruptedException). При этом, если вы заснули, держа ключ от комнаты (монитор), – ключ остаётся у вас, и никто не может войти.
На собеседовании. Два обязательных момента: (1)
sleep()не освобождает монитор – это классический подвопрос; (2)InterruptedException– не игнорируйте его, а обрабатывайте или восстанавливайте флаг прерывания черезThread.currentThread().interrupt(). Также можно упомянутьTimeUnit.SECONDS.sleep(5)как более читаемую альтернативуThread.sleep(5000).