В чем разница между wait()
и sleep()
в потоках?
Насколько я понимаю, что поток wait()
-ing по-прежнему находится в рабочем режиме и использует циклы процессора, но sleep()
-ing не требует каких-либо циклов процессора?
Почему у нас есть как wait()
, так и sleep()
: как их реализация меняется на более низком уровне?
wait
может быть "пробуждено" другим потоком, вызывающим notify
на мониторе, который ожидает, тогда как sleep
не может. Также wait
(и notify
) должно происходить в блоке, synchronized
на объекте монитора, тогда как sleep
не:
Object mon = ...;
synchronized (mon) {
mon.wait();
}
В этот момент текущий исполняющий поток ожидает и освобождает монитор. Другой поток может сделать
synchronized (mon) { mon.notify(); }
(на том же объекте mon
) и первый поток (при условии, что это единственный поток, ожидающий на мониторе) проснется.
Вы также можете вызвать notifyAll
если на мониторе ожидает более одного потока - это разбудит их всех. Однако только один из потоков сможет захватить монитор (помните, что wait
находится в synchronized
блоке) и продолжить - остальные будут заблокированы, пока они не получат блокировку монитора.
Другой момент заключается в том, что вы вызываете wait
для самого Object
(т.е. вы ждете на мониторе объекта), тогда как вы вызываете sleep
для Thread
.
Еще один момент заключается в том, что вы можете получить ложные пробуждения от wait
(то есть ожидающая нить возобновляется без видимой причины). Вы должны всегда wait
пока вращается на каком-то условии следующим образом:
synchronized {
while (!condition) { mon.wait(); }
}
Одно из ключевых различий, о которых еще не упоминалось, заключается в том, что во время сна нить не освобождает блокировки, которые она удерживает, ожидая освобождения блокировки объекта, на который вызывается wait()
.
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
Я нашел этот пост полезным. Это помещает различие между Thread.sleep()
, Thread.yield()
и Object.wait()
в человеческих терминах. Цитировать:
В конечном итоге все сводится к планировщику ОС, который раздает временные интервалы процессам и потокам.
sleep(n)
говорит: "Я закончил с моим временным интервалом, и, пожалуйста, не давайте мне еще один, по крайней мере, n миллисекунд". ОС даже не пытается планировать спящий поток, пока не истечет запрошенное время.
yield()
говорит: "Я закончил с моим временным интервалом, но у меня еще есть работа". ОС может немедленно предоставить потоку другой временной интервал, или дать другому потоку или обработать ЦП, который только что уступил исходящему потоку.
wait()
говорит: "Я закончил с моим временным интервалом. Не давайте мне другой временной интервал, пока кто-то не вызовет notify()". Как и сsleep()
, ОС даже не будет пытаться планировать вашу задачу, если кто-то не вызоветnotify()
(или не произойдет один из нескольких других сценариев пробуждения).Потоки также теряют остаток своего временного интервала, когда выполняют блокировку ввода-вывода и при некоторых других обстоятельствах. Если поток работает через весь временной интервал, ОС принудительно получает контроль, как если бы был вызван
yield()
, чтобы могли выполняться другие процессы.В редких случаях требуется
yield()
, но если у вас приложение с большими вычислительными возможностями и логическими границами задач, вставкаyield()
может повысить быстродействие системы (за счет времени - переключение контекста, даже только на ОС и обратно, не бесплатно).). Измеряйте и проверяйте цели, о которых вы заботитесь, как всегда.
sleep(n)
неявно говорит о том, что текущий запущенный поток добровольно освобождает монитор блокировки, что не соответствует действительности . Цитата из ветки Javadoc : «Нить не теряет права собственности ни на какие мониторы».
Здесь много ответов, но я не смог найти семантическое различие, упомянутое в любом из них.
Это не о самой нити; оба метода необходимы, поскольку они поддерживают очень разные варианты использования.
sleep()
отправляет Thread в режим сна, как раньше, он просто упаковывает контекст и прекращает выполнение в течение предопределенного времени. Поэтому, чтобы разбудить его до наступления срока, вам нужно знать ссылку на Thread. Это не обычная ситуация в многопоточной среде. Он в основном используется для синхронизации времени (например, разбудить ровно 3,5 секунды) и/или жестко закодированной справедливости (просто спать ненадолго и позволить другим потокам работать).
wait()
, напротив, является механизмом синхронизации потоков (или сообщений), который позволяет вам уведомлять нить, у которой у вас нет хранимой ссылки (и не заботы). Вы можете рассматривать это как шаблон публикации-подписки (wait
== subscribe и notify()
== publish). В основном, используя 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
synchronized(monitor){
while(condition == true){
monitor.wait() //releases monitor lock
}
Thread.sleep(100); //puts current thread on Sleep
}
Thread.sleep()
используется для того, чтобы сделать процессорное время доступным для других потоков. период ожидания может быть прерван прерываниями (т. е. JVM). Прочитайте это stackoverflow.com/questions/4264355/…
Есть некоторые отличительные ключевые заметки, которые я заключил после работы в режиме ожидания и сна, сначала взгляните на образец, используя wait() и sleep():
Пример1: используйте wait() и sleep():
synchronized(HandObject) {
while(isHandFree() == false) {
/* Hand is still busy on happy coding or something else, please wait */
HandObject.wait();
}
}
/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
/* Beer is still coming, not available, Hand still hold glass to get beer,
don't release hand to perform other task */
Thread.sleep(5000);
}
/* Enjoy my beer now ^^ */
drinkBeers();
/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
HandObject.notifyAll();
}
Позвольте пояснить некоторые ключевые замечания:
вы обычно используете sleep() для синхронизации времени и wait() для многопоточной синхронизации.
Пожалуйста, исправьте меня, если я ошибаюсь.
Принципиальное отличие состоит в том, что wait()
- это Object
а sleep()
- статический метод Thread
.
Основное отличие состоит в том, что wait()
снимает блокировку, а sleep()
не снимает блокировку во время ожидания.
wait()
используется для связи между потоками, в то время как sleep()
обычно используется для введения паузы при выполнении.
wait()
следует вызывать изнутри синхронизации, иначе мы получим IllegalMonitorStateException
, тогда как sleep()
может быть вызвана где угодно.
wait()
, вы должны позвонить notify()
или notifyAll()
. Что касается sleep(),
поток запускается через указанный интервал времени.Это очень простой вопрос, потому что оба эти метода имеют совершенно другое применение.
Основное различие заключается в том, чтобы ждать, чтобы выпустить блокировку или монитор, пока сон не отключает блокировку или монитор во время ожидания. Wait используется для межпоточной связи, в то время как сон используется для введения паузы при выполнении.
Это было просто ясное и основное объяснение, если вы хотите больше, чем продолжить чтение.
В случае wait()
поток метода переходит в состояние ожидания, и он не будет возвращаться автоматически, пока мы не назовем метод notify()
(или notifyAll()
, если в состоянии ожидания больше одного потока, и вы хотите разбудить все эти темы). Для доступа к методам wait()
или notify()
или notifyAll()
требуется синхронизация или блокировка объектов или блокировка классов. И еще одно, метод wait()
используется для межпоточной связи, потому что если поток переходит в состояние ожидания, вам понадобится другой поток, чтобы разбудить этот поток.
Но в случае sleep()
это метод, который используется для удерживания процесса в течение нескольких секунд или времени, которое вы хотели. Потому что вам не нужно вызывать метод notify()
или notifyAll()
, чтобы вернуть этот поток. Или вам не нужен какой-либо другой поток, чтобы перезвонить этому потоку. Например, если вы хотите, чтобы что-то произошло через несколько секунд, как в игре после поворота пользователя, вы хотите, чтобы пользователь подождал, пока компьютер не сыграет, вы можете упомянуть метод sleep()
.
И еще одно важное различие, которое часто задают в интервью: sleep()
принадлежит классу Thread
, а wait()
принадлежит классу Object
.
Это все различия между sleep()
и wait()
.
И есть сходство между обоими методами: оба они являются проверенными операторами, поэтому вам нужно попробовать catch или throw для доступа к этим методам.
Надеюсь, это поможет вам.
источник: http://www.jguru.com/faq/view.jsp?EID=47127
Thread.sleep()
отправляет текущий поток в состояние "Не работает" на некоторое количество времени. Поток поддерживает мониторы, которые он приобрел - то есть, если поток в настоящее время находится в синхронизированном блоке или методе, ни один другой поток не может ввести этот блок или метод. Если другой поток вызываетt.interrupt()
, он пробудит спящий поток.Обратите внимание, что сон - это статический метод, что означает, что он всегда влияет на текущий поток (тот, который выполняет метод сна). Общей ошибкой является вызов
t.sleep()
, где t - другой поток; даже тогда, это текущий поток, который будет спать, а не поток t.
t.suspend()
устарел. Используя его можно остановить поток другой чем текущий поток. Подвешенная нить держит все свои мониторы и так как это состояние не прерывается, оно является тупиковым.
object.wait()
отправляет текущий поток в состояние "Не запускается", какsleep()
, но с твист. Подождите, вызовите объект, а не нить; мы называем этот объект "объектом блокировки". Доlock.wait()
есть вызываемый, текущий поток должен синхронизировать объект блокировки;wait()
затем освобождает эту блокировку и добавляет поток в "список ожидания", связанных с блокировкой. Позже другой поток может синхронизироваться на тот же объект блокировки и вызовlock.notify()
. Это пробуждает оригинал, ожидающая нить. В принципе,wait()
/notify()
sleep()
/interrupt()
, только активная нить не нуждается в прямой указатель на спящий поток, но только на общий объект блокировки.
Ожидание и сон - это две разные вещи:
sleep()
поток прекращает работу в течение указанной продолжительности.wait()
поток прекращает работу до тех пор, пока ожидаемый объект не будет уведомлен, как правило, другими потоками. sleep
является методом Thread
, wait
является методом Object
, поэтому wait/notify
является методом синхронизации общих данных в Java (с использованием monitor), но sleep
- это простой метод потоковой паузы.
sleep() - это метод, который используется для удерживания процесса в течение нескольких секунд или времени, которое вы хотели, но в случае метода wait() поток переходит в состояние ожидания, и он не возвращается автоматически пока мы не вызываем notify() или notifyAll().
главное отличие заключается в том, что wait() освобождает блокировку или монитор, в то время как sleep() не выпускает блокировку или монитор во время ожидания. Wait используется для обмена данными между потоками, в то время как сон используется для введения паузы при выполнении, обычно.
Thread.sleep() отправляет текущий поток в состояние "Не запускается" в течение некоторого времени. Поток поддерживает мониторы, которые он приобрел - т.е. Если поток в настоящее время находится в синхронизированном блоке или методе, ни один другой поток не может ввести этот блок или метод. Если другой поток вызывает t.interrupt(), он пробудит спящий поток. Обратите внимание, что сон является статическим методом, что означает, что он всегда влияет на текущий поток (тот, который выполняет метод сна). Общей ошибкой является вызов t.sleep(), где t - другой поток; даже тогда, это текущий поток, который будет спать, а не поток t.
object.wait() отправляет текущий поток в состояние "Не запускается", например sleep(), но с завихрением. Ожидание вызывается на объект, а не на поток; мы называем этот объект "объектом блокировки". Перед вызовом функции lock.wait() текущий поток должен синхронизировать объект блокировки; wait() затем освобождает эту блокировку и добавляет поток в список ожидания, связанный с блокировкой. Позже другой поток может синхронизироваться на одном и том же объекте блокировки и вызвать lock.notify(). Это пробуждает оригинальную, ожидающую нитку. В принципе, wait()/notify() подобен sleep()/interrupt(), только активный поток не нуждается в прямом указателе на спящий поток, а только на объект общей блокировки.
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
Обозначим все вышеперечисленные точки:
Call on:
Synchronized:
Hold lock:
Wake-up condition:
Usage:
Ссылка: diff sleep
и wait
wait
и sleep
методы очень разные:
sleep
не имеет способа "просыпаться",wait
имеет способ "пробуждения" в течение периода ожидания, другим потоком, вызывающим notify
или notifyAll
.Подумайте об этом, имена в этом смысле сбивают с толку; однако sleep
- стандартное имя, а wait
- это WaitForSingleObject
или WaitForMultipleObjects
в Win API.
Из этой публикации: http://javaconceptoftheday.com/difference-between-wait-and-sleep-methods-in-java/
1) Поток, который вызывает метод wait(), освобождает блокировку.
2) Поток восстанавливает блокировку после того, как другие потоки вызывают методы notify() или notifyAll() при одной и той же блокировке.
3) метод wait() должен вызываться внутри синхронизированного блока.
4) метод wait() всегда вызывает объекты.
5) Ожидающие потоки можно разбудить другими потоками, вызвав методы notify() или notifyAll().
6) Чтобы вызвать метод wait(), поток должен иметь блокировку объекта.
1) Поток, который вызывает метод sleep(), не освобождает блокировку, которую он удерживает.
2) метод sleep() может быть вызван внутри или вне синхронизированного блока.
3) метод sleep() всегда вызывается в потоках.
4) Спящие нити не могут быть разбужены другими потоками. Если это будет сделано, поток будет вызывать InterruptedException.
5) Чтобы вызвать метод sleep(), потоку не требуется блокировка объекта.
Простыми словами ждать ждать До тех пор, пока какой-то другой поток не вызовет вас, тогда как sleep "не выполняет следующий оператор" в течение определенного периода времени.
Кроме того, sleep является статическим методом в классе Thread, и он работает с потоком, тогда как wait() находится в классе Object и вызывает объект.
Другой момент, когда вы вызываете wait на какой-либо объект, поток включает синхронизацию объекта и затем ждет.:)
сон
Wait
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()
делает нет.Создание исключения, когда это не нужно, неэффективно. Если у вас есть потоки, обменивающиеся друг с другом с высокой скоростью, тогда он будет генерировать множество исключений, если вы все время вызываете прерывание, что является полной потерей процессора.
wait
освобождает блокировку, а sleep
- нет. Поток в состоянии ожидания имеет право на пробуждение, как только вызывается notify
или notifyAll
. Но в случае sleep
поток сохраняет блокировку, и он будет иметь право только после истечения времени ожидания.
InterruptedException
, как сказано в Javadoc.
Ожидание() и сон() Различия?
Thread.sleep() Как только его работа будет завершена, только его освобождение будет заблокировано для всех. пока он никогда не освободит замок кому-либо.
Sleep() take the key, its never release the key to anyone, when its work completed then only its release then only take the key waiting stage threads.
Object.wait() Когда он перейдет на стадию ожидания, его будет выпустить ключ и его ожидание некоторых секунд на основе параметра.
Пример:
вы берете кофе в свою правую руку, вы можете взять другого кого-то из той же руки, когда вы положите его, а затем возьмите другой объект такого же типа здесь. также. это сон() вы спите время, когда у вас не было никакой работы, вы делаете только сон.. тоже здесь.
ожидание(). когда вы откладываете и принимаете еще одно среднее, пока вы ждете, подождите [/p >
вы играете в кино или что-нибудь в своей системе, так же как и игрок, вы не можете играть более одного раза за раз, то есть здесь, когда вы закрываете и выбираете другой, какой-либо фильм или песня означает, что он называется wait
Здесь wait() будет находиться в состоянии ожидания до тех пор, пока он не уведомит другой поток, но где, когда sleep() будет иметь некоторое время... после этого он автоматически перейдет в состояние готовности...
Методы используются для разных вещей.
Thread.sleep(5000); // Wait until the time has passed.
Object.wait(); // Wait until some other thread tells me to wake up.
Thread.sleep(n) может быть прерван, но Object.wait() должен быть уведомлен.
Можно указать максимальное время ожидания: Object.wait(5000)
, поэтому можно было бы использовать wait
to, er, sleep
, но тогда вам придется беспокоиться о блокировках.
Ни один из методов не использует процессор во время сна/ожидания.
Методы реализуются с использованием собственного кода, используя аналогичные конструкции, но не таким же образом.
Посмотрите сами: Доступен ли исходный код собственных методов? Файл /src/share/vm/prims/jvm.cpp
является отправной точкой...
Вы правы - Sleep() заставляет этот поток "спать", а процессор выключается и обрабатывает другие потоки (иначе они называются переключением контекста), я полагаю, что Wait поддерживает обработку процессора текущим потоком.
У нас есть то, что, хотя может показаться разумным позволить другим людям использовать процессор, пока вы его не используете, на самом деле есть накладные расходы для переключения контекста - в зависимости от продолжительности сна, это может быть дороже в циклы CPU для переключения потоков, чем просто для того, чтобы ваш поток ничего не делал в течение нескольких мс.
Также обратите внимание, что sleep заставляет контекстный переключатель.
Кроме того, в общем случае невозможно управлять переключением контекста - во время ожидания OS может (и будет для более длительного ожидания) выбирать для обработки других потоков.
От страницы документации оракала wait() метод Object
:
public final void wait()
notify()
или метод notifyAll()
для этого объекта. Другими словами, этот метод ведет себя точно так, как если бы он просто выполнял вызов wait(0)
.Этот метод выбрасывает
IllegalMonitorStateException
- если текущий поток не является владельцем монитора объекта.
InterruptedException
- если какой-либо поток прервал текущий поток до или пока текущий поток ожидает уведомления. Прерванный статус текущего потока очищается при этом исключении.
На странице документации оракула sleep() метод Thread
class:
public static void sleep(long millis)
Этот метод выдает:
IllegalArgumentException
- если значение миллиса отрицательно
InterruptedException
- если какой-либо поток прервал текущий поток. Прерванный статус текущего потока очищается при этом исключении.
Другое ключевое различие:
wait()
- это нестатический метод (метод экземпляра), в отличие от статического метода sleep()
(метод класса).
Должен вызываться из синхронизированного блока: wait()
метод всегда вызывается из синхронизированного блока. i.e. wait()
метод должен блокировать мониторинг объекта перед объектом, на который он вызывается. Но метод sleep()
может быть вызван из внешнего синхронизированного блока, то есть sleep()
не нужен какой-либо монитор объекта.
IllegalMonitorStateException:, если метод wait()
вызывается без обнаружения блокировки объекта, чем IllegalMonitorStateException
вызывается во время выполнения, но метод sleep()
никогда не выдает такое исключение.
Принадлежит классу wait()
к классу java.lang.Object
, но sleep()
принадлежит классу java.lang.Thread
.
Вызывается объект или поток: wait()
метод вызывается для объектов, но метод sleep()
вызывается в потоках не объектов.
Состояние темы:, когда на объект вызывается метод wait()
, поток, который хранит монитор объектов, переходит из состояния ожидания в состояние ожидания и может вернуться в состояние запуска только тогда, когда метод notify()
или notifyAll()
вызывается на этом объекте. И более поздний планировщик потоков планирует, что поток должен перейти от runnable к запущенному состоянию.
когда sleep()
вызывается в потоке, он переходит из состояния ожидания в состояние ожидания и может вернуться в состояние runnable, когда время ожидания больше.
При вызове из синхронизированного блока:, когда метод wait()
называется нитью, оставляет блокировку объекта. Но метод sleep()
при вызове из синхронизированного потока блоков или методов не оставляет блокировки объекта.
Для более Ссылка
Пример о сне не освобождает блокировку и ждет
Здесь есть два класса:
Singleton. Это одноэлементный класс с двумя статическими методами getInstance() и getInstance (boolean isWait).
public class Main {
private static Singleton singletonA = null;
private static Singleton singletonB = null;
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread() {
@Override
public void run() {
singletonA = Singleton.getInstance(true);
}
};
Thread threadB = new Thread() {
@Override
public void run() {
singletonB = Singleton.getInstance();
while (singletonA == null) {
System.out.println("SingletonA still null");
}
if (singletonA == singletonB) {
System.out.println("Both singleton are same");
} else {
System.out.println("Both singleton are not same");
}
}
};
threadA.start();
threadB.start();
}
}
и
public class Singleton {
private static Singleton _instance;
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
public static Singleton getInstance(boolean isWait) {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null) {
if (isWait) {
try {
// Singleton.class.wait(500);//Using wait
Thread.sleep(500);// Using Sleep
System.out.println("_instance :"
+ String.valueOf(_instance));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
_instance = new Singleton();
}
}
}
return _instance;
}
}
Теперь запустите этот пример, вы получите ниже вывода:
_instance :null
Both singleton are same
Здесь экземпляры Singleton, созданные threadA и threadB, одинаковы. Это означает, что threadB ждет снаружи до тех пор, пока threadA не отпустит его блокировку.
Теперь измените Singleton.java, комментируя Thread.sleep(500); метод и раскомментирование Singleton.class.wait(500);, Здесь из-за Singleton.class.wait(500); метод threadA будет освобождать все блокировки получения и перемещается в состояние "Non Runnable", threadB получит изменение для входа в синхронизированный блок.
Теперь снова запустите:
SingletonA still null
SingletonA still null
SingletonA still null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same
Здесь экземпляры Singleton, созданные threadA и threadB, НЕ совпадают, поскольку threadB получил изменение для входа в синхронизированный блок и после 500 миллисекунд threadA начал с последней позиции и создал еще один объект Singleton.
По моему мнению, основное различие между обоими механизмами заключается в том, что sleep/interrupt - самый простой способ обработки потоков, тогда как wait/notify - это абстракция, направленная на облегчение обмена данными между потоками. Это означает, что сон/прерывание может что-то сделать, но эта конкретная задача сложнее сделать.
Почему wait/notify больше подходит? Вот некоторые личные соображения:
Он обеспечивает централизацию.. Он позволяет координировать связь между группой потоков с одним общим объектом. Это значительно упрощает работу.
Он обеспечивает синхронизацию.. Это заставляет программиста переносить вызов на ожидание/уведомление в синхронизированном блоке.
Он не зависит от происхождения и количества потоков.. При таком подходе вы можете добавлять больше потоков произвольно без редактирования других потоков или отслеживания существующих. Если вы использовали sleep/interrupt, сначала вам нужно будет сохранить ссылки на спящие потоки, а затем прервать их один за другим, вручную.
Примером реальной жизни, которая хорошо объясняет это, является классический ресторан и метод, который персонал использует для общения между ними: официанты оставляют запросы клиентов в центральном месте (пробковая доска, стол и т.д..), звоните в колокольчик, и рабочие с кухни приходят, чтобы взять такие просьбы. Как только это будет готово к любому курсу, персонал кухни снова позвонит в колокольчик, чтобы официанты узнали и передали их клиентам.
sleep()
метод заставляет текущий поток переходить из состояния выполнения в состояние блокировки в течение заданного времени. Если текущий поток имеет блокировку любого объекта, он удерживает его, а это означает, что другие потоки не могут выполнять какой-либо синхронизированный метод в этом объекте класса.
wait()
метод приводит к тому, что текущий поток переходит в состояние блока либо в течение определенного времени, либо до уведомления, но в этом случае поток освобождает блокировку объекта (что означает, что другие потоки могут выполнять любые синхронизированные методы вызывающий объект.
wait со значением таймаута может просыпаться по истечении времени ожидания или уведомлять о том, что раньше (или прерывать), тогда как сон просыпается по истечении времени ожидания или прерывается в зависимости от того, что было раньше. wait() без значения тайм-аута будет ждать до тех пор, пока не будет уведомлено или прервано
Собственно, все это четко описано в документах Java (но я понял это только после прочтения ответов).
http://docs.oracle.com/javase/8/docs/api/index.html:
wait() - Текущий поток должен владеть этим объектом. Выпуски потоков владения этим монитором и ждет, пока другой поток не сообщит потоки, ожидающие на этом объектном мониторе, просыпаться либо через вызовите метод уведомления или метод notifyAll. Затем нить ждет, пока он не сможет повторно получить право собственности на монитор и возобновит выполнение.
sleep() - Заставляет текущий исполняемый поток спать (временно прекратить выполнение) за указанное количество миллисекунд, с учетом точности и точности системных таймеров и планировщиков. Нить не теряет права собственности на какие-либо мониторы.
wait(1000)
заставляет текущий поток спать до одной секунды.
notify()
или notifyAll()
вызов метода.sleep(1000)
заставляет текущий поток спать за ровно 1 секунду.
sleep(1000)
не гарантирует спать ровно 1 секунду. Это может быть прервано раньше.
wait()
задается внутри синхронизированного метода
тогда как sleep()
задается внутри несинхронизированного метода, потому что метод wait()
освобождает блокировку объекта, но sleep()
или yield()
освобождает lock()
.
sleep()
может быть внутри synchronized
блока или метода. Ответ ничего не объясняет.
Предположим, что вы слышите песни.
Пока текущая песня работает, следующая песня не будет воспроизводиться, т.е. Sleep() вызывается следующей песней
Если вы закончите песню, она остановится и пока вы не выберете кнопку воспроизведения (notify()), она не будет воспроизводиться, то есть wait(), вызванная текущей песней.
В обоих случаях песни идут в состояния Wait.