Разница между ожиданиями () и сном ()
В чем разница между wait()
а также sleep()
в темах?
Мое понимание того, что wait()
-ing Thread все еще находится в рабочем режиме и использует циклы процессора, но sleep()
-ing не потребляет никаких циклов процессора правильно?
Почему у нас есть оба wait()
а также sleep()
: как меняется их реализация на более низком уровне?
32 ответа
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()
отправляет поток в спящий режим, как это было раньше, он просто упаковывает контекст и прекращает выполнение в течение заданного времени. Поэтому, чтобы разбудить его раньше времени, вам нужно знать ссылку на тему. Это не обычная ситуация в многопоточной среде. Он в основном используется для синхронизации времени (например, пробуждение ровно через 3,5 секунды) и / или жестко закодированной справедливости (просто поспите некоторое время и позвольте другим потокам работать).
wait()
напротив, это механизм синхронизации потоков (или сообщений), который позволяет вам уведомлять поток, о котором у вас нет сохраненной ссылки (и нет никакой заботы). Вы можете думать об этом как о шаблоне публикации-подписки (wait
== подписаться и notify()
== опубликовать). В основном, используя notify(), вы отправляете сообщение (которое может даже не быть получено вообще, и обычно вас это не волнует).
Подводя итог, вы обычно используете sleep()
для синхронизации времени и wait()
для многопоточной синхронизации.
Они могут быть реализованы таким же образом в базовой ОС или не реализованы вовсе (так как предыдущие версии Java не имели реальной многопоточности; вероятно, некоторые небольшие виртуальные машины тоже этого не делают). Не забывайте, что Java работает на виртуальной машине, поэтому ваш код будет преобразован во что-то другое в соответствии с виртуальной машиной / операционной системой /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
}
Разница между ожиданиями () и сном ()
Принципиальная разница
wait()
изObject
а такжеsleep()
статический методThread
,Основное отличие состоит в том, что
wait()
снимает блокировку, покаsleep()
не снимает блокировку во время ожидания.wait()
используется для связи между потоками в то время какsleep()
обычно используется для ввода паузы на выполнение.wait()
следует позвонить изнутри синхронизировать, иначе мы получимIllegalMonitorStateException
в то время какsleep()
можно звонить куда угодно.- Чтобы начать тему снова с
wait()
, ты должен позвонитьnotify()
или жеnotifyAll()
, Пока вsleep(),
поток запускается через указанный интервал мс / сек.
Сходства, которые помогают понять
- И то, и другое заставляет текущий поток переходить в состояние Not Runnable.
- Оба
native
методы.
Есть некоторые заметки о ключевых отличиях, которые я заключаю после работы над wait и sleep, сначала рассмотрим пример, используя 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();
}
Позвольте прояснить некоторые ключевые примечания:
- Позвоните:
- wait (): вызов текущего потока, который содержит объект HandObject
- sleep (): вызовите выполнение задачи Thread, чтобы получить beer (это метод класса, который влияет на текущий работающий поток)
- Синхронизировано:
- wait (): когда синхронизируется многопоточный доступ к одному и тому же объекту (HandObject) (когда требуется связь между несколькими потоками (поток выполняет кодирование, поток выполняет get beer) доступ к одному и тому же объекту HandObject)
- sleep (): при выполнении условия ожидания для продолжения (ожидание пива доступно)
- Блокировка удержания:
- wait (): снять блокировку для другого объекта, который может быть выполнен (HandObject свободен, вы можете выполнять другую работу)
- sleep (): удерживать блокировку не менее t раз (или до прерывания) (моя работа все еще не завершена, я продолжаю удерживать блокировку и ожидаю выполнения какого-либо условия)
- Состояние пробуждения:
- wait (): до вызова notify (), notifyAll () из объекта
- sleep (): пока не истечет хотя бы время или прерывание вызова
- И последний пункт - использование, когда, как указывают estani:
вы обычно используете sleep () для синхронизации времени и wait () для многопоточной синхронизации.
Пожалуйста, поправьте меня, если я ошибаюсь.
Это очень простой вопрос, потому что оба эти метода имеют совершенно разное использование.
Основное отличие состоит в том, чтобы ждать, чтобы снять блокировку или монитор, в то время как сон не снимает блокировку или монитор во время ожидания. Ожидание используется для связи между потоками, в то время как режим сна используется для введения паузы при выполнении.
Это было просто ясное и простое объяснение, если вы хотите большего, тогда продолжайте читать.
В случае 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
Thread.sleep()
отправляет текущий поток в состояние "Не запускается" на некоторое время. Поток сохраняет мониторы, к которым он обратился - т.е. если поток в настоящее время находится в синхронизированном блоке или методе, никакой другой поток не может войти в этот блок или метод. Если другой поток вызываетt.interrupt()
это разбудит спящую нить.Обратите внимание, что sleep является статическим методом, что означает, что он всегда влияет на текущий поток (тот, который выполняет метод sleep). Распространенная ошибка - звонить
t.sleep()
где т другой поток; даже тогда будет текущий поток, а не поток.
t.suspend()
устарела. С его помощью можно остановить поток, отличный от текущего. Приостановленный поток сохраняет все свои мониторы, и, поскольку это состояние не прерываемо, он подвержен тупику.
object.wait()
отправляет текущий поток в состояние "не запускается", напримерsleep()
, но с изюминкой. Ожидание вызывается для объекта, а не для потока; мы называем этот объект "объект блокировки". Доlock.wait()
вызывается, текущий поток должен синхронизироваться на объекте блокировки;wait()
затем снимает эту блокировку и добавляет поток в "список ожидания", связанный с блокировкой. Позже другой поток может синхронизироваться с тем же объектом блокировки и вызыватьlock.notify()
, Это пробуждает оригинальную ожидающую нить. В принципе,wait()
/notify()
какsleep()
/interrupt()
только активному потоку не нужен прямой указатель на спящий поток, а только на объект общей блокировки.
Ждать и спать две разные вещи:
- В
sleep()
поток перестает работать на указанную продолжительность. - В
wait()
поток перестает работать до тех пор, пока ожидаемый объект не будет уведомлен, как правило, другими потоками.
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 (), только активному потоку не нужен прямой указатель на спящий поток, а только на объект общей блокировки.
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
Позвольте классифицировать все вышеперечисленные пункты:
Call on:
- wait (): вызов объекта; текущий поток должен синхронизироваться на объекте блокировки.
- sleep(): вызов по теме; всегда выполняющий поток
Synchronized:
- wait (): когда синхронизированные несколько потоков обращаются к одному и тому же объекту один за другим.
- sleep(): когда синхронизируются несколько потоков, ожидайте перерыва в спящем потоке.
Hold lock:
- wait (): снять блокировку для других объектов, чтобы иметь возможность выполнить.
- sleep(): удерживайте блокировку как минимум t раз, если указан тайм-аут или кто-то прервал.
Wake-up condition:
- wait (): до вызова notify (), notifyAll() из объекта
- sleep(): пока не истечет хотя бы время или вызов interrupt ().
Usage:
- 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()
это методObject
учебный класс.sleep()
это методThread
учебный класс.sleep()
позволяет потоку перейтиsleep
состояние за х миллисекунд.
Когда поток переходит в состояние снаit doesn’t release the lock
,wait()
позволяет потоку снять блокировку иgoes to suspended state
,
Эта тема будет активна, когдаnotify()
или жеnotifAll()
Метод вызывается для того же объекта.
Здесь wait() будет находиться в состоянии ожидания до тех пор, пока не получит уведомление от другого потока, но в течение некоторого времени, как sleep(), после чего он автоматически перейдет в состояние Ready...
Одна потенциальная большая разница между сном / прерыванием и ожиданием / уведомлением состоит в том, что
- призвание
interrupt()
в течениеsleep()
всегда выдает исключение (например, InterruptedException), тогда как - призвание
notify()
в течениеwait()
не.
Генерация исключения, когда оно не нужно, неэффективно. Если у вас есть потоки, которые общаются друг с другом с высокой скоростью, то вы бы генерировали много исключений, если бы вы все время вызывали прерывание, что является полной тратой процессорного времени.
спать
- Это заставляет текущий исполняющий поток спать в течение определенного времени.
- Его точность зависит от системных таймеров и планировщиков.
- Он сохраняет полученные мониторы, поэтому, если он вызывается из синхронизированного контекста, никакой другой поток не может войти в этот блок или метод.
- Если мы вызовем метод interrupt(), он разбудит спящий поток.
Подождите
- Это заставляет текущий поток ждать, пока другой поток не вызовет метод notify() или метод notifyAll() для этого объекта
- Он должен вызываться из синхронизированного контекста, т.е. из блока или метода. Это означает, что перед вызовом метода wait() текущий поток должен иметь блокировку для этого объекта.
- Он снимает блокировку с объекта, для которого он вызывается, и добавляется в список ожидания, поэтому другой поток может получить блокировку для объекта.
Вы правы - Sleep() приводит к тому, что поток "спит", и процессор отключается и обрабатывает другие потоки (иначе называемые переключением контекста), когда, я полагаю, Wait заставляет процессор обрабатывать текущий поток.
У нас есть и то и другое, потому что, хотя может показаться разумным позволить другим людям использовать процессор, пока вы его не используете, на самом деле существуют издержки на переключение контекста - в зависимости от того, как долго длится спящий режим, он может быть дороже в циклах процессора переключать потоки, чем просто заставить ваш поток ничего не делать в течение нескольких мс.
Также обратите внимание, что сон вызывает переключение контекста.
Кроме того - в общем случае невозможно управлять переключением контекста - во время ожидания ОС может (и будет дольше ожидать) выбрать обработку других потоков.
Методы используются для разных вещей.
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
э, sleep
но потом надо заморачиваться с замками.
Ни один из методов не использует процессор во время сна / ожидания.
Методы реализованы с использованием нативного кода, с использованием аналогичных конструкций, но не одинаковым образом.
Посмотрите сами: доступен ли исходный код нативных методов? Файл /src/share/vm/prims/jvm.cpp
это отправная точка...
wait
снимает блокировку и sleep
не делает. Поток в состоянии ожидания может проснуться, как только notify
или же notifyAll
называется. Но в случае sleep
поток сохраняет блокировку, и он будет иметь право только после окончания времени ожидания.
Wait() и sleep() Различия?
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 () Когда он перейдет в стадию ожидания, он отпустит ключ и будет ждать несколько секунд в зависимости от параметра.
Например:
вы берете кофе в свою правую руку, вы можете взять еще одного человека из той же руки, когда вы положите его, тогда возьмите только другой объект того же типа. также. это сон () вы спите время, когда у вас не было никакой работы, вы делаете только сон... то же самое и здесь.
Подождите(). когда вы подавлены и принимаете другое среднее значение, пока вы ждете, это ожидание
вы воспроизводите фильм или что-то в своей системе так же, как проигрыватель, вы не можете воспроизводить более одного видео одновременно, вот и все, когда вы закрываете и выбираете другой фильм или песню, означающие "время ожидания"
sleep()
Этот метод заставляет текущий поток переходить из состояния выполнения в состояние блокировки в течение указанного времени. Если текущий поток имеет блокировку какого-либо объекта, он продолжает удерживать ее, что означает, что другие потоки не могут выполнить какой-либо синхронизированный метод в этом объекте класса.
wait()
Метод заставляет текущий поток переходить в состояние блока либо на указанное время, либо до момента уведомления, но в этом случае поток снимает блокировку объекта (что означает, что другие потоки могут выполнять любые синхронизированные методы вызывающего объекта.
На мой взгляд, основное различие между обоими механизмами заключается в том, что режим сна / прерывания является самым основным способом обработки потоков, тогда как ожидание / уведомление - это абстракция, предназначенная для упрощения взаимодействия между потоками. Это означает, что сон / прерывание может делать что угодно, но эту конкретную задачу сложнее выполнить.
Почему ждать / уведомлять больше подходит? Вот некоторые личные соображения:
Это обеспечивает централизацию. Это позволяет координировать связь между группой потоков с одним общим объектом. Это значительно упрощает работу.
Это обеспечивает синхронизацию. Потому что это заставляет программиста обернуть вызов для ожидания / уведомления в синхронизированном блоке.
Это не зависит от происхождения и номера потока. При таком подходе вы можете добавлять дополнительные потоки произвольно, не редактируя другие потоки и не отслеживая существующие. Если вы использовали режим сна / прерывания, сначала вам нужно будет сохранить ссылки на спящие потоки, а затем прерывать их одну за другой вручную.
Пример из реальной жизни, который хорошо объяснить, это классический ресторан и метод, который персонал использует для общения между ними: официанты оставляют запросы клиентов в центральном месте (пробковая доска, стол и т. Д.), позвоните в звонок, и рабочие из кухни приходят, чтобы принять такие просьбы. Когда все готово, кухонный персонал снова звонит в колокольчик, чтобы официанты знали об этом и доставляли их покупателям.
Пример о сне не снимает блокировку, а ожидание делает
Здесь есть два класса:
- Main: содержит основной метод и два потока.
Singleton: это одноэлементный класс с двумя статическими методами getInstance() и getInstance (логическое 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 снимет все блокировки получения и переместится в состояние "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.
- Метод
wait(1000)
заставляет текущий поток спать до одной секунды.- Поток может спать менее 1 секунды, если он получает
notify()
или жеnotifyAll()
вызов метода.
- Поток может спать менее 1 секунды, если он получает
- Призыв к
sleep(1000)
заставляет текущий поток спать в течение ровно 1 секунды.- Также спящий поток не удерживает блокировку любого ресурса. Но ожидание потока делает.
Должен быть вызван из синхронизированного блока: wait()
метод всегда вызывается из синхронизированного блока, т.е. wait()
Метод должен блокировать монитор объекта перед объектом, для которого он вызывается. Но sleep()
метод может быть вызван извне синхронизированного блока, т.е. sleep()
Метод не нуждается ни в каком объектном мониторе.
IllegalMonitorStateException: если wait()
метод вызывается без получения блокировки объекта, чем IllegalMonitorStateException
бросается во время выполнения, но sleep()
метод никогда не выбрасывает такое исключение.
Принадлежит к какому классу: wait()
метод принадлежит java.lang.Object
класс но sleep()
метод принадлежит java.lang.Thread
учебный класс.
Вызывается на объект или поток: wait()
метод вызывается на объектах, но sleep()
Метод вызывается в потоках, а не объектах.
Состояние потока: когда wait()
метод вызывается для объекта, поток, в котором монитор удерживаемого объекта переходит из состояния ожидания в состояние ожидания и может вернуться в состояние выполнения только тогда, когда notify()
или же notifyAll()
метод вызывается для этого объекта. А позже планировщик потока планирует, что этот поток перейдет из рабочего состояния в рабочее. когда sleep()
вызывается в потоке, он переходит из рабочего состояния в состояние ожидания и может вернуться в рабочее состояние, когда время ожидания истекло.
При вызове из синхронизированного блока: когда wait()
Метод называется thread покидает объект блокировки. Но sleep()
Метод при вызове из синхронизированного блока или потока метода не покидает объектную блокировку.
Для получения дополнительной ссылки
Со страницы документации оракула о методе wait() Object
:
public final void wait()
- Заставляет текущий поток ждать, пока другой поток не вызовет
notify()
метод илиnotifyAll()
метод для этого объекта. Другими словами, этот метод ведет себя так, как будто он просто выполняет вызовwait(0)
, - Текущий поток должен владеть монитором этого объекта. Поток освобождает владельца этого монитора и ждет, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы проснуться
- возможны прерывания и ложные пробуждения
- Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта
Этот метод бросает
IllegalMonitorStateException
- если текущий поток не является владельцем монитора объекта.InterruptedException
- если какой-либо поток прервал текущий поток до или в то время, когда текущий поток ожидал уведомления. Прерванное состояние текущего потока очищается при возникновении этого исключения.
Со страницы документации оракула по методу sleep() Thread
учебный класс:
public static void sleep(long millis)
- Заставляет текущий исполняемый поток в спящий режим (временно прекращать выполнение) на указанное количество миллисекунд, в зависимости от точности и точности системных таймеров и планировщиков.
- Поток не теряет право собственности ни на какие мониторы.
Этот метод бросает:
IllegalArgumentException
- если значение миллис является отрицательнымInterruptedException
- если какой-либо поток прервал текущий поток. Прерванное состояние текущего потока очищается при возникновении этого исключения.
Другое ключевое отличие:
wait()
это нестатический метод (метод экземпляра) в отличие от статического метода sleep()
(метод класса).
Ожидание со значением тайм-аута может активироваться после истечения времени ожидания или уведомлять о том, что наступило раньше (или также прервать), тогда как сон просыпается по истечении времени ожидания или прерывания, в зависимости от того, что наступило раньше. wait() без значения тайм-аута будет ждать вечно, пока не будет извещено или прервано