Разница между "wait()" и "sleep()" в Java
Вопрос: В чем разница между методами wait()
и sleep()
в потоках?
Я хочу разобраться в различиях между wait()
и sleep()
в контексте работы с потоками в Java.
На мой взгляд, поток, находящийся в состоянии wait()
, остаётся в режиме выполнения и использует процессорные циклы, тогда как поток, который находится в состоянии sleep()
, не потребляет никакие процессорные циклы. Правильно ли я понимаю это различие?
Также меня интересует, почему у нас есть оба метода — wait()
и sleep()
?
Как различается их реализация на низком уровне?
Буду признателен за пояснения!
5 ответ(ов)
Одно ключевое различие, о котором ещё не было упомянуто:
sleep()
не освобождает захваченный поток "замок":synchronized(LOCK) { Thread.sleep(1000); // LOCK остается захваченным }
wait()
освобождает замок, который он удерживает на объекте:synchronized(LOCK) { LOCK.wait(); // LOCK не удерживается }
Это важно учитывать, так как использование sleep()
может привести к блокировке других потоков, ожидающих освобождения замка, в то время как wait()
позволяет другим потокам получить доступ к объекту в то время, когда текущий поток ожидает.
Существует много ответов на этот вопрос, но я не нашел упоминаемого семантического различия в них.
Дело не в самом потоке; оба метода необходимы, так как поддерживают очень разные сценарии использования.
sleep()
переводит поток в спящий режим, сохраняя его контекст, и останавливает выполнение на предопределенное время. Чтобы разбудить поток до истечения этого времени, вам нужно знать ссылку на поток. Это не распространенная ситуация в многопоточной среде. Он чаще всего используется для синхронизации времени (например, пробуждение через ровно 3,5 секунды) и/или жесткого соблюдения справедливости (просто немного поспать и дать возможность поработать другим потокам).
wait()
, напротив, является механизмом синхронизации потоков (или сообщений), который позволяет уведомить поток, на который у вас нет сохраненной ссылки (и о котором вы не заботитесь). Это можно рассматривать как паттерн "издатель-подписчик" (wait
== подписка, а notify()
== публикация). По сути, с помощью notify()
вы отправляете сообщение (которое может быть вообще не получено, и, как правило, вам на это все равно).
В общем, вы обычно используете sleep()
для синхронизации времени и wait()
для синхронизации в многопоточной среде.
Они могут быть реализованы одинаково в базовом операционном системе или вообще не реализованы (как это было в предыдущих версиях Java, где не было настоящего многопоточности; возможно, некоторые небольшие виртуальные машины также этого не делают). Не забывайте, что Java работает на виртуальной машине, поэтому ваш код будет преобразован в нечто иное в зависимости от используемой виртуальной машины/операционной системы/аппаратного обеспечения.
Разница между wait() и sleep()
- Основная разница заключается в том, что
wait()
является нестатическим методом классаObject
, в то время какsleep()
— статическим методом классаThread
. - Главное отличие в том, что
wait()
освобождает замок, в то время какsleep()
не освобождает никаких замков во время ожидания. wait()
используется для межпоточной коммуникации, тогда какsleep()
обычно применяется для введения паузы в выполнении.wait()
должен вызываться внутри блока синхронизации, иначе возникнетIllegalMonitorStateException
, тогда какsleep()
можно вызывать в любом месте.- Чтобы снова запустить поток из состояния
wait()
, необходимо вызватьnotify()
илиnotifyAll()
, как бы бесконечно. В случае сsleep()
, поток обязательно возобновляет выполнение после заданного времени.
Сходства
- Оба метода переводят текущий поток в состояние Not Runnable.
- Оба являются нативными методами.
Это очень простой вопрос, так как оба этих метода имеют совершенно разное назначение.
Основное различие заключается в том, что wait()
освобождает блокировку или монитор, тогда как sleep()
не освобождает никакую блокировку или монитор во время ожидания. wait()
используется для межпоточной коммуникации, в то время как sleep()
используется для введения паузы в выполнении программы.
Это было простое и ясное объяснение. Если вам нужно больше деталей, читайте дальше.
В случае метода wait()
поток переходит в состояние ожидания и не вернется автоматически, пока мы не вызовем метод notify()
(или notifyAll()
, если у вас более одного потока в состоянии ожидания и вы хотите разбудить их всех). Для доступа к методам wait()
, notify()
или notifyAll()
требуется синхронизированный блок, объектная блокировка или класс-лок. Также стоит отметить, что метод wait()
используется для межпоточной коммуникации, поскольку, когда поток переходит в состояние ожидания, вам нужен другой поток, чтобы его разбудить.
В случае метода sleep()
это метод, который используется для приостановки исполнения на несколько секунд или на тот промежуток времени, который вы хотите. Вам не нужно вызывать notify()
или notifyAll()
, чтобы вернуть этот поток к работе, и нет необходимости, чтобы другой поток поднимал этот поток. Например, если вы хотите, чтобы после хода пользователя в игре прошло время, прежде чем компьютер сделает свой ход, вы можете использовать метод sleep()
.
Еще одно важное различие, которое часто спрашивают на собеседованиях: sleep()
принадлежит классу Thread
, а wait()
принадлежит классу Object
.
Это все различия между sleep()
и wait()
.
Также есть одно сходство между этими двумя методами: оба метода являются проверяемыми, поэтому для их использования вам необходимо обрабатывать исключения с помощью try-catch
или throws
.
Надеюсь, это поможет вам.
wait()
и sleep()
— это два разных метода:
- В
sleep()
поток приостанавливает свою работу на указанное время. - В
wait()
поток приостанавливает свою работу до тех пор, пока объект, на который он ждет, не будет уведомлён, обычно другими потоками.
"implements Runnable" против "extends Thread" в Java: что выбрать?
Как работают сервлеты? Инстанцирование, сессии, общие переменные и многопоточность
Что значит 'synchronized'?
Как установить Java 8 на Mac
Почему в RecyclerView отсутствует onItemClickListener()?