В чем разница между a wait()
и sleep()
в потоках?
Насколько я понимаю, wait()
поток -ing все еще находится в рабочем режиме и использует циклы ЦП, но sleep()
-ing не использует правильные циклы ЦП?
Почему у нас есть и то, wait()
и другоеsleep()
: как их реализация меняется на более низком уровне?
Ответы:
A
wait
может быть "разбужен" другим потоком, вызывающимnotify
монитор, которого ожидают, тогда как asleep
не может. Такжеwait
(иnotify
) должно происходить в блокеsynchronized
объекта монитора, тогда какsleep
:На этом этапе текущий выполняющий поток ожидает и освобождает монитор . Другой поток может сделать
(на том же
mon
объекте) и первый поток (при условии, что это единственный поток, ожидающий на мониторе) проснется.Вы также можете позвонить,
notifyAll
если более одного потока ожидает на мониторе - это разбудит их всех . Однако только один из потоков сможет захватить монитор (помните, что онwait
находится вsynchronized
блоке) и продолжить - остальные будут заблокированы, пока не получат блокировку монитора.Другое дело, что вы звоните
wait
поObject
себе (то есть вы будете ждать на мониторе объекта) , тогда как вы звонитеsleep
наThread
.Еще один момент заключается в том, что вы можете получать ложные пробуждения от
wait
(то есть ожидающая нить возобновляется без видимой причины). Вы всегдаwait
должны вращаться при некоторых условиях следующим образом:источник
wait
/notify
обычно используются для ожидания выполнения задачи другим потоком или для ожидания выполнения определенного условия.Одно из ключевых различий пока не упоминается, что во время сна на тему никак не освободить замки она держит, во время ожидания снимает блокировку на объект , который
wait()
называется на.источник
sleep
содержит блокировки Java , но это не так. Для того, чтобы иметь сравнение справедливой, мы бы сравнитьsynchronized(OUTER_LOCK){ Thread.sleep(1000); }
сsynchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} }
и мы можем видеть , что обе команды не отпуститьOUTER_LOCK
. Если есть какая-то разница, мы можем сказать, что вsleep
явном виде не используются блокировки Java , но возникает вопрос о цитате "как их реализация меняется на более низком уровне?" Unquote.wait()
связан с состоянием самой внутренней блокировки, из которой он вызывается , в вашем примере кодаwait()
может только освобождаться,LOCK
а неOUTER_LOCK
. Вот как все-таки создан Java-монитор. Справедливое сравнение было быsynchronized(OUTER_LOCK){ synchronized(LOCK) { Thread.sleep(1000); } }
иsynchronized(OUTER_LOCK){ synchronized(LOCK) { LOCK.wait(); } }
. В этом случаеsleep()
будет держать оба замка , покаwait()
выпустят ,LOCK
но по- прежнему держатьOUTER_LOCK
Я нашел этот пост полезным. Это ставит разницу между
Thread.sleep()
,Thread.yield()
иObject.wait()
в человеческом плане. Цитировать:источник
sleep(n)
косвенно говорит о том, что текущий запущенный поток добровольно освобождает монитор блокировки, что не соответствует действительности . Цитата из ветки Javadoc : «Нить не теряет право собственности ни на какие мониторы».sleep
он не имеет никакого особого поведения в отношении монитора, чем любой другой вызов метода Java, то есть он не взаимодействует и не изменяет их каким-либо образом. Если вы хотите что-то сказать о мониторах, вы должны указать, чтоwait
в дополнение к вышеперечисленным вещам временно снимет блокировку с вызываемого объекта.wait(n)
для сравненияsleep(n)
. Нет смысла сравнивать использование без аргументов.Здесь много ответов, но я не смог найти семантического различия, упомянутого ни в одном.
Дело не в самой теме; оба метода необходимы, поскольку они поддерживают очень разные варианты использования.
sleep()
отправляет поток в спящий режим, как это было раньше, он просто упаковывает контекст и прекращает выполнение в течение предопределенного времени. Поэтому, чтобы разбудить его раньше времени, вам нужно знать ссылку на тему. Это не обычная ситуация в многопоточной среде. Он в основном используется для синхронизации времени (например, пробуждение ровно через 3,5 секунды) и / или жестко закодированной справедливости (просто поспите некоторое время и позвольте другим потокам работать).wait()
напротив, это механизм синхронизации потоков (или сообщений), который позволяет вам уведомлять поток, о котором у вас нет сохраненной ссылки (и нет никакой заботы). Вы можете думать об этом как о шаблоне публикации-подписки (wait
== подписка иnotify()
== публикация). В основном с помощью notify () вы отправляете сообщение (которое может даже не быть получено вообще, и обычно вас это не волнует).Подводя итог, вы обычно используете
sleep()
для синхронизации времени иwait()
для многопоточной синхронизации.Они могут быть реализованы таким же образом в базовой ОС или не реализованы вовсе (так как в предыдущих версиях Java не было реальной многопоточности; вероятно, некоторые небольшие виртуальные машины тоже этого не делают). Не забывайте, что Java работает на виртуальной машине, поэтому ваш код будет преобразован во что-то другое в соответствии с VM / OS / HW, на которой он работает.
источник
Здесь я перечислил несколько важных различий между
wait()
иsleep()
методы.PS: Также нажмите на ссылки, чтобы увидеть код библиотеки (внутренняя работа, просто поиграйте немного для лучшего понимания).
Подождите()
wait()
метод снимает блокировкуwait()
это методObject
класса.wait()
это нестатический метод -public final void wait() throws InterruptedException { //...}
wait()
должен быть уведомленnotify()
илиnotifyAll()
методы.wait()
метод должен вызываться из цикла, чтобы справиться с ложной тревогой.wait()
метод должен быть вызван из синхронизированного контекста (т.е. синхронизированный метод или блок), иначе он будет выбрасыватьIllegalMonitorStateException
спать()
sleep()
метод не снимает блокировкуsleep()
это методjava.lang.Thread
класса.sleep()
это статический метод -public static void sleep(long millis, int nanos) throws InterruptedException { //... }
sleep()
завершено.sleep()
лучше не звонить из цикла (т.е. см. код ниже ).sleep()
может быть вызван откуда угодно. нет конкретных требований.Ссылка: разница между ожиданием и сном
Фрагмент кода для вызова метода wait и sleep
источник
Thread.sleep()
используется для предоставления процессорного времени доступным другим потокам. период ожидания может быть прерван прерываниями (т. е. JVM). Прочитайте это stackoverflow.com/questions/4264355/…notify()
илиnotifyAll()
являютсяObject
методами класса. следовательно, они доступны для всех классов (т. е. и дляThread
классов). см. код grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…Есть некоторые заметки о ключевых отличиях, которые я заключаю после работы над wait и sleep, сначала рассмотрим пример, используя wait () и sleep ():
Пример 1 : использование wait () и sleep ():
Позвольте прояснить некоторые ключевые примечания:
Пожалуйста, поправьте меня, если я ошибаюсь.
источник
Разница между ожиданиями () и сном ()
Принципиальное отличие заключается в том, что
wait()
отObject
иsleep()
является статическим методомThread
.Основное отличие состоит в том, что
wait()
освобождает блокировку, ноsleep()
не снимает блокировку во время ожидания.wait()
используется для связи между потоками, в то времяsleep()
как обычно используется для приостановки выполнения.wait()
должен быть вызван изнутри синхронизировать, иначе мы получимIllegalMonitorStateException
, в то время какsleep()
может быть вызван в любом месте.wait()
, вы должны позвонитьnotify()
илиnotifyAll()
. Что касаетсяsleep(),
потока запускается через указанный промежуток времени.сходства
источник
Это очень простой вопрос, потому что оба эти метода имеют совершенно разное использование.
Основным отличием является ожидание, чтобы снять блокировку или монитор, в то время как сон не снимает блокировку или монитор во время ожидания. Ожидание используется для связи между потоками, в то время как режим сна используется для введения паузы при выполнении.
Это было просто ясное и простое объяснение, если вы хотите большего, тогда продолжайте читать.
В случае, когда
wait()
метод переходит в состояние ожидания, он не будет возвращаться автоматически, пока мы не вызовемnotify()
метод (илиnotifyAll()
если у вас более одного потока в состоянии ожидания и вы хотите разбудить все эти потоки). А для доступа к методамwait()
илиnotify()
или вам нужна синхронизация, либо блокировка объекта, либо блокировка классаnotifyAll()
. И еще одна вещь,wait()
метод используется для связи между потоками, потому что если поток переходит в состояние ожидания, вам понадобится другой поток, чтобы разбудить этот поток.Но в случае
sleep()
этого есть метод, который используется для удержания процесса в течение нескольких секунд или нужного вам времени. Потому что вам не нужно вызывать какой-notify()
либоnotifyAll()
метод или метод, чтобы вернуть этот поток. Или вам не нужен какой-либо другой поток, чтобы перезвонить этому потоку. Например, если вы хотите, чтобы что-то произошло через несколько секунд, как в игре после поворота пользователя, вы хотите, чтобы пользователь ждал, пока компьютер начнет играть, тогда вы можете упомянутьsleep()
метод.И еще одно важное различие , которое часто спрашивают в интервью:
sleep()
принадлежит кThread
классу иwait()
относится кObject
классу.Это все различия между
sleep()
иwait()
.И у обоих методов есть сходство: они оба являются проверенным оператором, поэтому вам нужно попробовать catch или throws для доступа к этим методам.
Я надеюсь, что это поможет вам.
источник
источник: http://www.jguru.com/faq/view.jsp?EID=47127
источник
Ждать и спать две разные вещи:
sleep()
потоке перестает работать на указанную продолжительность.wait()
потоке перестает работать до тех пор, пока ожидаемый объект не будет уведомлен, как правило, другими потоками.источник
sleep
, если вы хотите, чтобы он остановился, пока какой-то вход не поступит от другого, который вы используетеwait
/notify
.interrupt
предназначено как способ сообщить потоку, что он должен прекратить делать то, что он делает, и завершиться. Он обрабатываетсяsleep
,wait
но также блокирует функции ввода / вывода (и вы можете реализовать функции с таким же поведением, вызвав методThread.interrupted()
). Что касается производительности, функции обычно оптимизируются в соответствии с целью, для которой они были разработаны.sleep
Это методThread
,wait
методObject
, такwait/notify
же как и метод синхронизации общих данных в Java (с использованием монитора ), ноsleep
это простой метод потоковой приостановки самого себя.источник
sleep () - это метод, который используется для удержания процесса в течение нескольких секунд или нужного времени, но в случае, когда метод метода wait () переходит в состояние ожидания, и он не возвращается автоматически, пока мы не вызовем notify () или notifyAll ().
Основное отличие состоит в том, что wait () снимает блокировку или монитор, в то время как sleep () не снимает блокировку или монитор во время ожидания. Ожидание используется для связи между потоками, в то время как ожидание используется, чтобы вообще ввести паузу при выполнении.
Thread.sleep () отправляет текущий поток в состояние «Not Runnable» на некоторое время. Поток хранит полученные им мониторы, т. Е. Если поток находится в синхронизированном блоке или методе, никакой другой поток не может войти в этот блок или метод. Если другой поток вызывает t.interrupt (), он разбудит спящий поток. Обратите внимание, что sleep - это статический метод, который означает, что он всегда влияет на текущий поток (тот, который выполняет метод sleep). Распространенной ошибкой является вызов t.sleep (), где t - другой поток; даже тогда будет текущий поток, а не поток.
object.wait () отправляет текущий поток в состояние «не запускается», как sleep (), но с поворотом. Ожидание вызывается для объекта, а не для потока; мы называем этот объект «объект блокировки». Перед вызовом lock.wait () текущий поток должен синхронизироваться с объектом блокировки; Затем wait () снимает эту блокировку и добавляет поток в «список ожидания», связанный с блокировкой. Позже другой поток может синхронизироваться с тем же объектом блокировки и вызывать lock.notify (). Это пробуждает оригинальную ожидающую нить. По сути, wait () / notify () похожа на sleep () / interrupt (), только активному потоку не нужен прямой указатель на спящий поток, а только на объект общей блокировки.
Позвольте классифицировать все вышеперечисленные пункты:
Call on:
Synchronized:
Hold lock:
Wake-up condition:
Usage:
Ref: diff
sleep
иwait
источник
Проще говоря, wait is wait До тех пор, пока какой-то другой поток не вызовет вас, тогда как sleep «не выполняет следующую инструкцию» в течение определенного периода времени.
Кроме того, sleep является статическим методом в классе Thread и работает с потоком, тогда как wait () находится в классе Object и вызывается для объекта.
Другой момент, когда вы вызываете wait для какого-либо объекта, вовлеченный поток синхронизирует объект и затем ожидает. :)
источник
wait
иsleep
методы очень разные:sleep
не имеет возможности «проснуться»,wait
есть способ «пробуждения» в течение периода ожидания, вызываемый другим потокомnotify
илиnotifyAll
.Если подумать, имена сбивают с толку в этом отношении; однако
sleep
это стандартное имя иwait
похоже наWaitForSingleObject
илиWaitForMultipleObjects
в Win API.источник
Из этого поста: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/
Метод wait ().
1) Поток, который вызывает метод wait (), снимает блокировку, которую он удерживает.
2) Поток восстанавливает блокировку после того, как другие потоки вызывают методы notify () или notifyAll () для той же блокировки.
3) метод wait () должен быть вызван в синхронизированном блоке.
4) метод wait () всегда вызывается для объектов.
5) Ожидающие потоки могут быть разбужены другими потоками путем вызова методов notify () или notifyAll ().
6) Для вызова метода wait () поток должен иметь блокировку объекта.
Метод сна ()
1) Поток, который вызывает метод sleep (), не снимает блокировку, которую он удерживает.
2) метод sleep () может быть вызван внутри или снаружи синхронизированного блока.
3) метод sleep () всегда вызывается в потоках.
4) Спящие нитки не могут быть разбужены другими нитями. Если это сделано, поток выдаст исключение InterruptedException.
5) Чтобы вызвать метод sleep (), поток не должен иметь объектную блокировку.
источник
Здесь wait () будет находиться в состоянии ожидания до тех пор, пока не получит уведомление от другого потока, но когда у функции sleep () будет некоторое время ... после этого он автоматически перейдет в состояние готовности ...
источник
wait()
это методObject
класса.sleep()
это методThread
класса.sleep()
позволяет потоку перейти вsleep
состояние в течение x миллисекунд.Когда поток переходит в состояние сна
it doesn’t release the lock
.wait()
позволяет потоку снять блокировку иgoes to suspended state
.Этот поток будет активен при вызове метода
notify()
илиnotifAll()
для того же объекта.источник
Одна потенциальная большая разница между сном / прерыванием и ожиданием / уведомлением состоит в том, что
interrupt()
течениеsleep()
всегда вызывает исключение (например, InterruptedException ), тогда какnotify()
во времяwait()
нет.Создание исключения, когда оно не нужно, неэффективно. Если у вас есть потоки, взаимодействующие друг с другом с высокой скоростью, то вы бы генерировали много исключений, если бы вы все время вызывали прерывание, что является полной тратой процессорного времени.
источник
Вы правы - Sleep () приводит к тому, что поток «спит», и процессор отключается и обрабатывает другие потоки (иначе называемые переключением контекста), когда, я полагаю, Wait заставляет процессор обрабатывать текущий поток.
У нас есть и то и другое, потому что, хотя может показаться разумным позволить другим людям использовать процессор, пока вы его не используете, на самом деле существуют издержки на переключение контекста - в зависимости от того, как долго длится спящий режим, он может быть дороже в циклах процессора переключать потоки, чем просто заставить ваш поток ничего не делать в течение нескольких мс.
Также обратите внимание, что сон вызывает переключение контекста.
Кроме того - в общем случае невозможно управлять переключением контекста - во время ожидания ОС может (и будет дольше ожидать) выбрать обработку других потоков.
источник
interrupt
. Время окончанияn
вwait(n)
. 8 Прошло 8 лет, и до сих пор никто не имеет ответа!Методы используются для разных вещей.
Thread.sleep (n) может быть прерван, но Object.wait () должен быть уведомлен. Можно указать максимальное время ожидания:
Object.wait(5000)
так что можно было бы использоватьwait
его,sleep
но тогда вам придется беспокоиться о блокировках.Ни один из методов не использует процессор во время сна / ожидания.
Методы реализованы с использованием нативного кода, с использованием аналогичных конструкций, но не одинаковым образом.
Посмотрите сами: доступен ли исходный код нативных методов? Файл
/src/share/vm/prims/jvm.cpp
является отправной точкой ...источник
Thread.sleep(big_num)
должен быть прерван.Object.wait(small_num)
можно уведомить.Wait () и sleep () Различия?
Thread.sleep () После того, как его работа завершена, только снятие блокировки для всех. пока его никогда не откроет замок никому.
Object.wait () Когда он перейдет в стадию ожидания, он отпустит ключ и будет ждать несколько секунд в зависимости от параметра.
Например:
Вы берете кофе в свою правую руку, вы можете взять еще одного человека из той же руки, когда вы положите его, тогда возьмите только другой объект того же типа. также. это сон () вы спите время, когда у вас не было никакой работы, вы делаете только сон ... то же самое и здесь.
Подождите(). когда вы подавлены и принимаете другое среднее значение, пока вы ждете, это ожидание
вы воспроизводите фильм или что-то в своей системе так же, как проигрыватель, вы не можете воспроизводить более одного видео одновременно, вот и все, когда вы закрываете и выбираете другой фильм или песню, означающее, что время ожидания
источник
wait
снимает блокировку иsleep
не делает Поток в состоянии ожидания , имеет право на пробуждение , как толькоnotify
илиnotifyAll
называются. Но в случае,sleep
если поток сохраняет блокировку, он будет иметь право только после окончания времени ожидания.источник
InterruptedException
брошен, как говорится в Javadoc.sleep()
Метод заставляет текущий поток переходить из состояния выполнения в состояние блокировки в течение указанного времени. Если текущий поток имеет блокировку какого-либо объекта, он продолжает удерживать ее, что означает, что другие потоки не могут выполнить какой-либо синхронизированный метод в этом объекте класса.wait()
Метод заставляет текущий поток переходить в состояние блока либо на указанное время, либо до момента уведомления, но в этом случае поток снимает блокировку объекта (что означает, что другие потоки могут выполнять любые синхронизированные методы вызывающего объекта.источник
На мой взгляд, основное различие между обоими механизмами заключается в том, что режим сна / прерывания является самым основным способом обработки потоков, тогда как ожидание / уведомление - это абстракция, предназначенная для упрощения взаимодействия между потоками. Это означает, что сон / прерывание может делать что угодно, но эту конкретную задачу сложнее выполнить.
Почему ждать / уведомлять больше подходит? Вот некоторые личные соображения:
Это обеспечивает централизацию. Это позволяет координировать связь между группой потоков с одним общим объектом. Это значительно упрощает работу.
Это обеспечивает синхронизацию. Потому что это заставляет программиста обернуть вызов для ожидания / уведомления в синхронизированном блоке.
Это не зависит от происхождения и номера потока. При таком подходе вы можете добавлять дополнительные потоки произвольно, не редактируя другие потоки и не отслеживая существующие. Если вы использовали режим сна / прерывания, сначала вам нужно будет сохранить ссылки на спящие потоки, а затем прерывать их одну за другой вручную.
Пример из реальной жизни, который хорошо объяснить, это классический ресторан и метод, который персонал использует для общения между ними: официанты оставляют запросы клиентов в центральном месте (пробковая доска, стол и т. Д.), позвоните в звонок, и рабочие с кухни приходят, чтобы принять такие просьбы. Когда все готово, кухонный персонал снова звонит в колокольчик, чтобы официанты знали и доставляли их покупателям.
источник
Пример сна не снимает блокировку, а ожидание делает
Здесь есть два класса:
Singleton : это одноэлементный класс с двумя статическими методами getInstance () и getInstance (логическое isWait).
а также
Теперь запустите этот пример, вы получите ниже вывод:
Здесь экземпляры Singleton, созданные threadA и threadB, одинаковы. Это означает, что threadB ожидает снаружи, пока threadA не снимет свою блокировку.
Теперь измените Singleton.java, комментируя Thread.sleep (500); метод и раскомментирование Singleton.class.wait (500); , Здесь из-за Singleton.class.wait (500); метод threadA снимет все блокировки получения и переместится в состояние «Runnable», а threadB получит изменение для входа в синхронизированный блок.
Теперь запустите снова:
Здесь экземпляры Singleton, созданные threadA и threadB, НЕ одинаковы, потому что threadB получил изменение для входа в синхронизированный блок и после 500 миллисекунд threadA начал с своей последней позиции и создал еще один объект Singleton.
источник
Должен вызываться из синхронизированного блока:
wait()
метод всегда вызывается из синхронизированного блока, т. Е.wait()
Метод должен блокировать монитор объекта перед объектом, для которого он вызывается. Ноsleep()
метод может быть вызван извне синхронизированного блока, т.е.sleep()
Метод не нуждается ни в каком объектном мониторе.IllegalMonitorStateException: если
wait()
метод вызывается без получения блокировки объекта, он генерируетсяIllegalMonitorStateException
во время выполнения, ноsleep()
метод никогда не генерирует такое исключение.Принадлежит к какому классу:
wait()
метод принадлежитjava.lang.Object
классу, ноsleep()
метод принадлежитjava.lang.Thread
классу.Вызывается для объекта или потока:
wait()
метод вызывается для объектов, ноsleep()
метод вызывается для потоков, а не объектов.Состояние
wait()
потока : когда метод вызывается для объекта, поток, который удерживает монитор объекта, переходит из состояния ожидания в состояние ожидания и может вернуться в состояние выполнения только при вызовеnotify()
илиnotifyAll()
метода этого объекта. А позже планировщик потока планирует, что этот поток перейдет из рабочего состояния в рабочее. Когдаsleep()
вызывается в потоке, он переходит из состояния ожидания в состояние ожидания и может вернуться в состояние выполнения, когда время ожидания истекло.При вызове из синхронизированного блока: при
wait()
вызове метода поток покидает объектную блокировку. Ноsleep()
метод при вызове из синхронизированного блока или потока метода не оставляет объектную блокировку.Для получения дополнительной ссылки
источник
Со страницы документации оракула о методе wait ()
Object
:notify()
метод илиnotifyAll()
метод для этого объекта. Другими словами, этот метод ведет себя точно так же, как если бы он просто выполнял вызовwait(0)
.Этот метод бросает
IllegalMonitorStateException
- если текущий поток не является владельцем монитора объекта.InterruptedException
- если какой-либо поток прервал текущий поток до или в то время, когда текущий поток ожидал уведомления. Прерванное состояние текущего потока очищается при возникновении этого исключения.Со страницы документации оракула по методу sleep ()
Thread
класса:Этот метод бросает:
IllegalArgumentException
- если значение миллис является отрицательнымInterruptedException
- если какой-либо поток прервал текущий поток. Прерванное состояние текущего потока очищается при возникновении этого исключения.Другое ключевое отличие:
wait()
это нестатический метод (метод экземпляра) в отличие от статического методаsleep()
(метод класса).источник
wait()
дается внутри синхронизированного метода, тогдаsleep()
как дается внутри несинхронизированного метода, потому чтоwait()
метод освобождает блокировку объекта, ноsleep()
илиyield()
освобождаетlock()
.источник
sleep()
может быть внутриsynchronized
блока или метода. Ответ ничего не объясняет.wait(1000)
заставляет текущий поток спать до одной секунды .notify()
илиnotifyAll()
.sleep(1000)
текущий поток спит ровно 1 секунду .источник
sleep(1000)
не гарантирует спать ровно 1 секунду. Это может быть прервано раньше.Собственно, все это четко описано в документации Java (но я понял это только после прочтения ответов).
http://docs.oracle.com/javase/8/docs/api/index.html :
wait () - текущему потоку должен принадлежать монитор этого объекта. Поток освобождает владельца этого монитора и ожидает, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы он проснулся либо посредством вызова метода notify, либо метода notifyAll. Затем поток ожидает, пока не получит право собственности на монитор, и возобновит выполнение.
sleep () - Заставляет текущий выполняющийся поток спать (временно прекращать выполнение) на указанное количество миллисекунд, в зависимости от точности и точности системных таймеров и планировщиков. Поток не теряет права собственности ни на какие мониторы.
источник