Вопрос по multithreading, java – Разница между ожиданиями () и сном ()

1106

В чем разница междуwait() а такжеsleep() в темах?

Мое понимание того, чтоwait()-ing Thread все еще находится в рабочем режиме и использует циклы процессора, ноsleep()-ing не потребляет никаких циклов процессора правильно?

Почему у насboth wait() а такжеsleep(): как меняется их реализация на более низком уровне?

очень хороший вопрос. семантику обоих легко спутать. Andreas Petersson
Очень хорошие вопросы, но они 2 в одном. Почему у нас оба не такие, как они могут (и не являются!) Реализованы на более низком уровне. Я тоже ответил на это. estani
Вот хорошая статья, описывающая это: Qat.com / с использованием-waitnotify-вместо-нить-сон-Java Triton Man
Предположим, что поток A находится в синхронизированном блоке, и в то время как он находится в процессоре из этого потока, он берется и передается другому потоку B. Теперь, в каком состоянии будет находиться поток A, будут ли поступать другие потоки, ожидающие этого синхронизированного блока. в настоящее время Peter
itCATLY наоборот - sleep "использует" все доступные циклы CPU, но поскольку поток будет находиться в состоянии "WAITING", их можно при необходимости вернуть - фактически большинство операционных систем автоматически выдают циклыЕСЛ это возможно, следовательно, ваш поток не будет создавать фактическую нагрузку на процессор ... он будет делать это на старых операционных системах. Object.wait (), с другой стороныНИКОГД использует любые циклы (хотя и не уведомленные), потому что во многих случаях они реализуются через программные прерывания - частные, временные и прозрачные блокировки, реализованные JVM. Thread.sleep - плохая практика. specializt

Ваш Ответ

30   ответов
783

A 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(); }
}
Спящий поток также можно разбудить с помощью notify (). ? Geek
Нет, не может. Это может быть только прервано. Peter Štibraný
@ Geek - почему в мире вы говорите, что wait () тратит время процессора? Robert Munteanu
Interrupt предназначен для мягкого побуждения потока к полной остановке и отмене оставшихся операций.wait/notify обычно используются для ожидания какого-либо другого потока для выполнения задачи или для ожидания выполнения определенного условия. Louis Wasserman
Я прочитал все ответы, но мне все еще не хватает информации. Многие люди записали определения из Javadoc, а также значение двух английских слов, но я не понимаю, почему я должен когда-либо использовать сон вместо ожидания? Какова разница в скорости между тестами? Если я могу делать все, что я могу делать со сном, почему я должен когда-либо выбирать сон? Balazs Zsoldos
311

о которых еще не говорилось, заключается в том, что во время сна потн снимает блокировки, которые он удерживает, а ожидание снимает блокировку с объекта, которыйwait() вызывается.

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}
Ожидание только снимает блокировку для объекта, который вывызо wait () вкл. Не выпускает ни одногоДруги замки Jon Skeet
На самом деле вам не нужно вызывать сон изнутри - блокировки и ожидание / уведомление идут рука об руку, но блокировки и сон не связаны. oxbow_lakes
@ oxbow_lakes - я бы сказал, что не стоит спать с замками, для этого есть несколько вариантов использования. Просто хотел указать на различия. Robert Munteanu
@ RobertMunteanu, Ваш ответ вводит в заблуждение, чтоsleep держитДжав блокирует, но это не так. Чтобы иметь справедливое сравнение, мы бы сравнилиsynchronized(OUTER_LOCK){ Thread.sleep(1000); } сsynchronized(OUTER_LOCK){ synchronized(LOCK){LOCK.wait();} } и мы видим, что обе инструкции не выпускаютOUTER_LOCK. Если есть какая-либо разница, мы можем сказать, чтоsleep явно не Использование Джав блокирует, но вопрос заключается в цитате "как их реализация меняется на более низком уровне?" Unquote. Pacerier
@ Pacerierwait() связано с состоянием самой внутренней блокировки, из которой он вызывается, в вашем примере кода,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 danze
217

эта почт полезно. Это ставит разницу междуThread.sleep(), Thread.yield(), а такжеObject.wait() в человеческом смысле. Цитировать

Все это в конечном итоге сводится к планировщику ОС, который раздает временные интервалы процессам и потокам.

sleep(n) говорит «Я справился со своим временным интервалом, и, пожалуйста, не давай мне еще один по крайней мере n миллисекунд». ОС даже не пытается запланировать спящий поток, пока не истечет запрошенное время.

yield() говорит «Я закончила работу с расписанием, но у меня еще есть работа». Операционная система может сразу же дать потоку другой временной интервал, или дать другому потоку, или обработать процессор, который уступил выходному потоку.

wait() говорит «Я закончила работу с расписанием. Не давайте мне еще один временной интервал, пока кто-нибудь не позвонит notify (). Как сsleep(), операционная система даже не попытается запланировать вашу задачу, если кто-то не позвонитnotify() (или один из нескольких других сценариев пробуждения).

Threads также теряют остаток своего временного интервала, когда выполняют блокировку ввода-вывода и при некоторых других обстоятельствах. Если поток работает через весь временной интервал, ОС принудительно берет на себя управление, как если быyield() был вызван, чтобы могли выполняться другие процессы.

Тебе редко нужноyield(), но если у вас приложение с большими вычислительными возможностями и логическими границами задач, вставьтеyield() может быт улучшить отзывчивость системы (за счет времени - переключение контекста, даже только на ОС и обратно, не бесплатно). Измеряйте и проверяйте цели, о которых вы заботитесь, как всегда.

Выход в основном зависит от платформы ... Javamex.com / учебники / темы / yield.shtml Pacerier
объяснениеsleep(n) неявно говорит, что текущий запущенный поток добровольно отказывается от монитора блокировки, то естьне правд. Цитата из Javadoc нити: «Нить не теряет право собственности ни на какие мониторы.» Clint Eastwood
@ Джонатан, в ответе нет упоминания о мониторах, и это потому, чтоsleep не имеет никакого специального поведения в отношении монитора, чем любой другой вызов метода Java, то есть он не взаимодействует и не изменяет их каким-либо образом. Если вы хотите что-то сказать о мониторах, вы должны указать, чтоwait, в дополнение к вышеупомянутым вещам, временно снимет блокировку с объекта, к которому она обращена. pqnet
Как работает уведомление на уровне планировщика ОС? Вызывает ли notify какой-либо обработчик событий с определенным идентификатором потока, позволяющий планировщику вернуть соответствующий поток обратно в текущую очередь? Также у меня есть еще один вопрос, куда вписывается концепция спин-блокировки? Будет ли это актуально только для сна или он сам использует спинлок на очень низком уровн CMCDragonkai
65

но я не смог найти семантического различия, упомянутого ни в одном.

Дело не в самой теме; оба метода необходимы, поскольку они поддерживают очень разные варианты использования.

sleep() отправляет поток в спящий режим, как это было раньше, он просто упаковывает контекст и прекращает выполнение в течение предопределенного времени. Поэтому, чтобы разбудить его раньше времени, вам нужно знать ссылку на тему. Это не обычная ситуация в многопоточной среде. В основном он используется для синхронизации времени (например, пробуждение ровно через 3,5 секунды) и / или жестко закодированной справедливости (просто поспите некоторое время и позвольте другим потокам работать).

wait(), напротив, представляет собой механизм синхронизации потоков (или сообщений), который позволяет вам уведомлять поток, на который у вас нет сохраненной ссылки (и не заботитесь). Вы можете думать об этом как о шаблоне публикации-подписки wait == подписаться иnotify() == опубликовать). В основном с помощью notify () вы отправляете сообщение (которое может даже не быть получено вообще, и обычно вас это не волнует).

Подводя итог, вы обычно используетеsleep() для синхронизации времени иwait() для многопоточной синхронизации.

Они могут быть реализованы таким же образом в базовой ОС, или не реализованы вовсе (поскольку предыдущие версии Java не имели реальной многопоточности; вероятно, некоторые небольшие виртуальные машины тоже этого не делают). Не забывайте, что Java работает на виртуальной машине, поэтому ваш код будет преобразован во что-то другое в соответствии с VM / OS / HW, на которой он работает.

48

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() можно вызывать откуда угодно. особых требований нет.

Ref: Разница между ожиданием и сном

Фрагмент кода для вызова метода ожидания и сна

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

Правильно ли, что спящий поток может быть разбужен вызовами notify ()? Некоторые из других сообщений здесь, по-видимому, подразумевают, что спящая тема не может быть разбужена, но прервана. berimbolo
Да,Thread.sleep() используется для того, чтобы сделать процессорное время доступным для других потоков. период ожидания может быть прерван прерываниями (то есть JVM). Прочитайте это / Stackoverflow.com вопросы / 4264355 / ... roottraveller
В этом посте также говорится, что interrupt () - это то, что пробуждает спящую нить? Я имел в виду диаграмму состояния потока, которую вы опубликовали, где написано «уведомить» или «уведомить». Все данные возвращают спящий (не ожидающий) поток к готовности к работе. Я просто хочу убедиться, что понимаю это. berimbolo
@ berimbolonotify() илиnotifyAll() являютсяObject методы класса. следовательно, они доступны для всех классов (т. е. здесь сThread класс тоже). см код Grepcode.com / файл / repository.grepcode.com / Java / корень / JDK / OpenJDK / ... roottraveller
OK Мне нужно больше узнать о планировании потоков, так как я не могу найти примеры, когда notify () или notifyAll () пробуждают спящие потоки только interrupt (), делающей это. Все примеры связывают notify () и notifyAll () с потоками, ожидающими некоторый объект монитора. berimbolo
28

которые я заключаю после работы над ожиданием и сном, сначала рассмотрим пример с помощью wait () и sleep ():

Example1: с помощьюПодождит() а такжеспат ():

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 (): вызов текущего потока, который содержит объект HandObjectsleep (): вызовите задачу выполнения потока, чтобы получить пиво (это метод класса, который влияет на текущий работающий поток) Синхронное:wait (): при синхронизированном многопоточном доступе к одному и тому же объекту (HandObject) (при необходимости связи между несколькими потоками (поток выполняет кодирование, поток выполняет получение пива) доступ к одному и тому же объекту HandObject)sleep (): при выполнении условия ожидания для продолжения (ожидание пива доступно) Держать замок:wait (): снять блокировку для другого объекта, есть шанс выполнения (HandObject свободен, вы можете выполнять другую работу)sleep (): удерживать блокировку не менее t раз (или до прерывания) (моя работа все еще не завершена, я продолжаю удерживать блокировку и ожидаю выполнения какого-либо условия) Состояние пробуждения:wait (): до вызова notify (), notifyAll () из объектаsleep (): пока не истечет хотя бы время или прерывание вызова И последний пунктuse когда как Estani указывает:

Вы обычно используете sleep () для синхронизации времени и wait () для синхронизации нескольких потоков.

Пожалуйста, поправь меня, если я ошибаюсь.

5

wait is wait До тех пор, пока какой-то другой поток не вызовет вас, тогда как sleep "не выполняет следующую инструкцию" в течение определенного периода времени.

Moreover sleep - это статический метод в классе Thread, который работает с потоком, тогда как wait () находится в классе Object и вызывается для объекта.

Другой момент: когда вы вызываете wait для какого-либо объекта, вовлеченный поток синхронизирует объект, а затем ожидает. :)

Почему тебе нужны оба? Почему sleep () недостаточно? Geek
Notify используется для связи между потоками. Чтобы вызвать wait, вам нужен какой-то объект, синхронизировать его, а затем вызвать wait на нем. Чтобы получать уведомления, вам нужен другой поток для синхронизации наодно и тож возражать и звонить уведомлять. Peter Štibraný
22
Разница между ожиданиями () и сном ()

wait() изObject а такжеsleep() - это статический методThread.

Главное отличие в том, чтоwait() снимает блокировку, покаsleep() не снимает блокировки во время ожидания.

wait() используется для связи между потоками, в то время какsleep() обычно используется для ввода паузы в исполнение.

wait() следует вызывать изнутри синхронизации, иначе мы получимIllegalMonitorStateException, в то время какsleep() можно позвонить куда угодно.

Чтобы начать тему снова сwait(), ты должен позвонитьnotify() илиnotifyAll(). Что касаетсяsleep(), поток запускается через указанный промежуток времени. Сходства Как сделать текущий поток в Не работает штатОбародно методы.
18

потому что оба эти метода имеют совершенно разное использование.

Основное различие заключается в том, чтобы ждать, чтобы снять блокировку или монитор, в то время как сон не снимает блокировку или монитор во время ожидания. Wait используется для связи между потоками, в то время как sleep используется для введения паузы при выполнении.

Это было просто ясное и простое объяснение, если хочешь большего, продолжай читать.

В случаеwait()оток метода @ переходит в состояние ожидания и не возвращается автоматически, пока мы не вызовемnotify() метод (илиnotifyAll() если у вас более одного потока в состоянии ожидания и вы хотите разбудить все эти потоки). И вам нужно синхронизировать или объектную блокировку или классовую блокировку для доступа кwait() илиnotify() илиnotifyAll() методы. И еще одна вещь,wait()етод @ используется для связи между потоками, потому что если поток переходит в состояние ожидания, вам понадобится другой поток, чтобы разбудить этот поток.

Но в случаеsleep() это метод, который используется для удержания процесса в течение нескольких секунд или нужного времени. Потому что вам не нужно провоцироватьnotify() илиnotifyAll() метод, чтобы вернуть эту тему. Или вам не нужен какой-либо другой поток, чтобы перезвонить этому потоку. Например, если вы хотите, чтобы что-то произошло через несколько секунд, как в игре после поворота пользователя, вы хотите, чтобы пользователь ждал, пока компьютер не заиграет, вы можете упомянутьsleep() метод.

И еще одно важное отличие, которое часто задают в интервью:sleep() принадлежитThread класс иwait() принадлежитObject учебный класс

Это все различия междуsleep() а такжеwait().

И у обоих методов есть сходство: они оба являются проверенным оператором, поэтому вам нужно попробовать catch или throws для доступа к этим методам.

Я надеюсь, что это поможет вам

16

http: //www.jguru.com/faq/view.jsp EID = 47127

Thread.sleep() отправляет текущий поток в "Не работает" указать какое-то время. Поток сохраняет мониторы, к которым он обратился, т.е. если поток в настоящее время находится в синхронизированном блоке или методе, никакой другой поток не может войти в этот блок или метод. Если другой поток вызываетt.interrupt() это разбудит спящую нить.

Отметим, что sleep является статическим методом, что означает, что он всегда влияет на текущий поток (тот, который выполняет метод sleep). Распространенная ошибка - звонитьt.sleep() где t - другая тема; даже в этом случае будет спать текущий поток, а не поток t.

t.suspend() не рекомендуется. С его помощью можно остановить поток, отличный от текущего. Приостановленный поток сохраняет все свои мониторы, и, поскольку это состояние не прерывается, он подвержен тупику.

object.wait() отправляет текущий поток в "Не работает" состояние, какsleep(), но с изюминкой. Ожидание вызывается для объекта, а не для потока; мы называем этот объект «объект блокировки». Доlock.wait() вызывается, текущий поток должен синхронизироваться на объекте блокировки;wait()атем @ снимает эту блокировку и добавляет поток в «список ожидания», связанный с блокировкой. Позже другой поток может синхронизироваться с тем же объектом блокировки и вызыватьlock.notify(). Это пробуждает оригинальную ожидающую нить. В основном,wait()/notify() какsleep()/interrupt(), только активный поток не нуждается в прямом указателе на спящий поток, а только на объект общей блокировки.

14

Вsleep() поток перестает работать в течение указанного периода времени.Вwait() поток перестает работать до тех пор, пока ожидаемый объект не будет уведомлен, как правило, другими потоками.
но вы можете прервать спящий поток. В этом случае wait () является избыточным, потому что он также теряет циклы процессора: - Geek
Wait не тратит впустую циклы процессора. Peter Štibraný
@ Питер - я думаю, что так и есть. Он ждет () для своей части циклов ЦП, а затем ОС передает циклы ЦП другим потокам. Я думаю, что это может зависеть от ОС, я не уверен. Geek
Это было бы очень плохой реализацией wait (), если бы она теряла циклы процессора. wait / notify довольно часто используется для межпотокового общения. Peter Štibraný
@ Pacerier две конструкции предназначены для разных целей. Если вы хотите, чтобы поток останавливался на фиксированное время, вы используетеsleep, если вы хотите, чтобы он прекратился до тех пор, пока какой-либо вход не поступит от другого, который вы используетеwait/notify. interrupt предназначен для того, чтобы сигнализировать потоку, что он должен прекратить делать то, что он делает, и завершиться. Обрабатываетсяsleep, wait но также блокирует функции ввода-вывода (и вы можете реализовать забавные выражения с тем же поведением, вызвав методThread.interrupted()). Что касается производительности, функции, как правило, оптимизируются для достижения цели. pqnet
11

sleep это методThread, wait это методObject, такwait/notify - это метод синхронизации общих данных в Java (использование Монитор), ноsleep - это простой метод потоковой приостановки самого себя.

7

спать( - это метод, который используется для удержания процесса в течение нескольких секунд или нужного вам времени, но в случае, когда поток метода wait () переходит в состояние ожидания, и он не возвращается автоматически, пока мы не вызовем notify () или notifyAll ( ).

The большая разница в том, чтоПодождите( снимает блокировку или монитор, пока sleep () не снимает блокировку или монитор во время ожидания. Ожидание используется для связи между потоками, в то время как режим сна обычно используется для введения паузы при выполнени

Thread.sleep () отправляет текущий поток в состояние «Не работает» на некоторое время. Поток сохраняет мониторы, которые он получил, т.е. если поток в настоящее время находится в синхронизированном блоке или методе, никакой другой поток не может войти в этот блок или метод. Если другой поток вызывает t.interrupt (), он разбудит спящий поток. Обратите внимание, что sleep - это статический метод, который означает, что он всегда влияет на текущий поток (тот, который выполняет метод sleep). Распространенной ошибкой является вызов 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:

Подождите() снять блокировку для других объектов, чтобы иметь возможность выполнить.спать() держите блокировку не менее t раз, если указан тайм-аут или кто-то прерывает.

Wake-up condition:

Подождите() до вызова notify (), notifyAll () из объектаспать() пока не истечет хотя бы время или вызовите прерывание ().

Usage:

спать() для синхронизации времени и;Подождите() для многопоточной синхронизации.

Ref: Diffsleep а такжеwait

6

wait а такжеsleep методы очень разные:

sleep не может "проснуться",в то время какwait @ есть способ «пробуждения» в течение периода ожидания, когда другой поток вызываnotify илиnotifyAll.

Подумай об этом, имена сбивают с толку в этом отношении; тем не мениеsleep - это стандартное имя иwait это какWaitForSingleObject илиWaitForMultipleObjects в Win API.

Но мы можем прерватьспат не могли бы мы? так в чем же разница с этим сном / прерыванием против ожидания / уведомления? Pacerier
Вы можете прервать спящего человека, но можете уведомить только ожидающего. Темы одинаковые. Rishi
3

пока он не уведомит об этом другой Поток, но где время как sleep () будет иметь некоторое время ... после этого он автоматически перейдет в состояние Готов ...

5

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 (), поток должен иметь блокировку объекта.

sleep () Метод

1) Поток, который вызывает метод sleep (), не снимает блокировку, которую он удерживает.

2) метод sleep () может быть вызван внутри или снаружи синхронизированного блока.

3) метод sleep () всегда вызывается в потоках.

4) Спящие нити не могут быть разбужены другими нитями. Если это так, поток выдаст исключение InterruptedException.

5) Чтобы вызвать метод sleep (), поток не должен иметь объектную блокировку.

4

wait() это методObject учебный класс
sleep() это методThread учебный класс

sleep() позволяет ветке перейти кsleep состояние в течение x миллисекунд.
Когда поток переходит в состояние снаit doesn’t release the lock.

wait() позволяет потоку снять блокировку иgoes to suspended state.
Этот поток будет активен, когдаnotify() илиnotifAll() метод вызывается для того же объекта.

4

м / уведомлением заключается в том, что

звонокinterrupt() в течениеsleep() всегда выдает исключение (например, InterruptedException), в то время ка звонокnotify() в течениеwait() не

Создание исключения, когда оно не нужно, неэффективно. Если у вас есть потоки, взаимодействующие друг с другом с высокой скоростью, то вы бы генерировали много исключений, если бы вы все время вызывали прерывание, что является полной тратой процессорного времени.

+ 1, на самом деле правильная точка, хотя и спор о Внутренности реализаций может быть более подходящим для анализа производительности ... Pacerier
3

и процессор отключается и обрабатывает другие потоки (иначе называемые переключением контекста), когда, я полагаю, Wait заставляет процессор обрабатывать текущий поток.

У нас есть и то и другое, потому что, хотя может показаться разумным позволить другим людям использовать процессор, а вы его не используете, на самом деле есть издержки на переключение контекста - в зависимости от того, как долго длится сон, он может быть дороже в процессоре циклически переключает потоки, чем просто заставляет ваш поток ничего не делать в течение нескольких мс.

Также обратите внимание, что сон вызывает переключение контекста.

Также - в общем случае невозможно управлять переключением контекста - во время ожидания ОС может (и будет дольше ждать) выбрать обработку других потоков.

wait () не сохраняет процессор, обрабатывающий текущий поток. Это похоже на сон в том, что оно вызывает переключение контекста: Javamex.com / учебники / темы / context_switch.shtml. Я просил пол года на стекопотоке, и кажется, что никто не знает, в чем разница между ожиданием / уведомлением и сном / прерыванием. Pacerier
думаю, что @ sleepough не удерживает процессор в обработке текущего потока, в любом случае, это немного обременительно для процессора, потому что процессору нужно отслеживать момент, когда закончится сон. У него нет такого внешнего триггера, как "notify" в ожидании. Нет? Vladimir Nabokov
3

Методы используются для разных вещей.

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 является отправной точкой ...

ремя @ Thread.sleep также может быть установлено на неопределенное время. Время Object.wait также может быть установлено на определенный. Этот ответ не объясняет, почему нам нужны 2 молотка, которые делают то же самое. Pacerier
3

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 () Когда он перейдет в стадию ожидания, он отпустит ключ и будет ждать несколько секунд в зависимости от параметра.

Например

Вы берете кофе в свою правую руку, вы можете взять еще одного человека из той же руки, когда вы положите его, тогда возьмите только другой объект того же типа. также. это сон () вы спите время, когда у вас не было никакой работы, вы делаете только сон ... то же самое и здесь.

Подождите(). когда вы подавлены и принимаете другое среднее значение, пока вы ждете, это подождит

Вы воспроизводите фильм или что-то в своей системе так же, как проигрыватель, который вы не можете воспроизводить более чем по одному, верно, вот и здесь, когда вы закрываете и выбираете другой фильм или песню, в то время как это называется wait

3

wait снимает блокировку иsleep нет. Поток в состоянии ожидания может проснуться, как толькоnotify илиnotifyAll называется. Но в случаеsleep поток сохраняет блокировку, и он будет иметь право только после окончания времени ожидания.

Так что, если поток спит в течение 10 секунд, и возникает прерванное исключение ???? Geek
@ Geek AnInterruptedException брошен, как сказано в Javadoc. user207421
@ EJP: Вы тот же EJP, кто был на форумах sun.java.com? По крайней мере, ваш счет говорит о том же: -) Geek
2

sleep()етод @ заставляет текущий поток переходить из состояния выполнения в состояние блокировки в течение указанного времени. Если текущий поток имеет блокировку какого-либо объекта, он продолжает удерживать ее, что означает, что другие потоки не могут выполнить какой-либо синхронизированный метод в этом объекте класса.

wait() метод заставляет текущий поток переходить в состояние блока либо на указанное время, либо до момента уведомления, но в этом случае поток снимает блокировку объекта (что означает, что другие потоки могут выполнять любые синхронизированные методы вызывающего объекта.

2

основное различие между обоими механизмами заключается в том, что режим сна / прерывания является самым основным способом обработки потоков, тогда как wait / notify - это абстракция, предназначенная для упрощения взаимодействия между потоками. Это означает, что сон / прерывание может делать что угодно, но эту конкретную задачу сложнее выполнить.

Почему стоит подождать / сообщить больше? Вот некоторые личные соображения:

Он обеспечивает централизацию. Позволяет координировать связь между группой потоков с одним общим объектом. Это значительно упрощает работу.

Это обеспечивает синхронизацию. Потому что это заставляет программиста обернуть вызов для ожидания / уведомления в синхронизированном блоке.

Он не зависит от происхождения и номера нити. При таком подходе вы можете добавлять больше потоков произвольно, не редактируя другие потоки и не отслеживая существующие. Если вы использовали режим сна / прерывания, сначала вам нужно будет сохранить ссылки на спящие потоки, а затем прерывать их одну за другой вручную.

Пример из реальной жизни, который хорошо объяснить, это классический ресторан и метод, который персонал использует для общения между ними: официанты оставляют запросы клиентов в центральном месте (пробковая доска, стол и т. Д.) Позвоните в колокол, и рабочие с кухни приходят, чтобы принять такие просьбы. Когда все готово, кухонный персонал снова звонит в колокольчик, чтобы официанты знали и доставляли их покупателям.

2

Здесь есть два класса:

Главны: Содержит основной метод и два потока.

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 :[email protected]
SingletonA still null
SingletonA still null
SingletonA still null
Both singleton are not same

Здесь экземпляры Singleton, созданные threadA и threadB, НЕ одинаковы, потому что threadB получил изменение для входа в синхронизированный блок, и через 500 миллисекунд threadA начал с последней позиции и создал еще один объект Singleton.

2

Должен вызываться из синхронизированного блока: 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()етод @ при вызове из синхронизированного блока или потока метода не покидает объектную блокировку.

Для большегоСсылк

вероятно, лучший URL ссылки, чем этот. Drew
2

Со страницы документации оракула наПодождите( методObject:

public final void wait()
Приводит текущий поток к ожиданию, пока другой поток не вызоветnotify() метод илиnotifyAll() метод для этого объекта. Другими словами, этот метод ведет себя точно так же, как если бы он просто выполнял вызовwait(0). Текущий поток должен иметь монитор этого объекта. Поток освобождает владельца этого монитора и ожидает, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы он проснулс прерывания и ложные пробуждения возможны Этот метод должен вызываться только потоком, который является владельцем монитора этого объекта

Этот метод бросает

IllegalMonitorStateException - если текущий поток не является владельцем монитора объекта.

InterruptedException - если какой-либо поток прерывал текущий поток до или в то время, когда текущий поток ожидал уведомления. Прерванное состояние текущего потока очищается при возникновении этого исключения.

Со страницы документации оракула наспать( методThread учебный класс

public static void sleep(long millis)
Переводит текущий выполняющийся поток в спящий режим (временно прекращает выполнение) на указанное количество миллисекунд, в зависимости от точности и точности системных таймеров и планировщиков.The thread does not lose ownership of any monitors

This method throws

IllegalArgumentException - if the value of millis is negativ

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown

Other key difference

wait() is a non-static method (instance method) unlike static methodsleep() (class method)

1

wait() is given inside a synchronized method whereassleep() is given inside a non-synchronized method becausewait() method release the lock on the object butsleep() oryield() does release thelock().

sleep() can be inside asynchronized block or method. Answer explains nothing user207421
1

ify whichever is earlier (or interrupt as well), whereas, a sleep wakes up on timeout value elapsed or interrupt whichever is earlier. wait() with no timeout value will wait for ever until notified or interrupte

1
Методwait(1000) causes the current thread to sleepup to one secon.A thread could sleep less than 1 second if it receives thenotify() ornotifyAll() method call Призыв кsleep(1000) causes the current thread to sleep forexactly 1 secon.Такжеsleeping thread doesn't hold lock any resourc. But waiting thread does
sleep(1000) doesn't guaranty to sleep for exactly 1 second. It may may be interrupted before Lucio
These posts are so confusing. All the other posts on this thread say that a sleeping thread DOES hold the lock and that a waiting thread DOESNT hold the lock. Similarly the post with the diagram implies that calls to notify() wake sleeping threads but other posts (and thread state diagrams) imply that only interrupt() or the timeout period passing do this. I just ordered myself a copy of java concurrency in practice, something I should have read a long time ago berimbolo
in sleep thread doesn't releases the loc subhashis

Похожие вопросы