Разница между ожиданиями () и сном ()

1075

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

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

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

  • 42
    очень хороший вопрос семантику обоих легко спутать.
  • 1
    Очень хорошие вопросы, но они 2 в одном. Почему у нас оба не такие, как они могут (и не являются!) Реализованы на более низком уровне. Я тоже ответил на это.
Показать ещё 4 комментария
Теги:
multithreading
sleep
java-threads

33 ответа

725
Лучший ответ

wait может быть "пробуждено" другим потоком, вызывающим notify на мониторе, который ожидает, тогда как sleep не может. Также waitnotify) должно происходить в блоке, 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(); }
}
  • 21
    Спящий поток также может быть вызван функцией notify (). ?
  • 125
    Нет, не может. Это может быть только прервано.
Показать ещё 20 комментариев
315

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

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


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}
  • 97
    Ожидание только снимает блокировку для объекта, для которого вы вызываете wait (). Это не освобождает никаких других замков.
  • 14
    На самом деле вам не нужно вызывать sleep изнутри блокировки - блокировки и ожидание / уведомление идут рука об руку, но блокировки и сон не связаны.
Показать ещё 8 комментариев
214

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

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

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

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

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

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

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

  • 0
    Доходность в основном зависит от платформы ... javamex.com/tutorials/threads/yield.shtml
  • 0
    объяснение sleep(n) неявно говорит о том, что текущий запущенный поток добровольно освобождает монитор блокировки, что не соответствует действительности . Цитата из ветки Javadoc : «Нить не теряет права собственности ни на какие мониторы».
Показать ещё 2 комментария
62

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

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

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

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

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

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

46

Здесь я перечислил несколько важных различий между методами wait() и sleep().
PS: Также нажмите на ссылки, чтобы увидеть код библиотеки (внутренняя работа, просто поиграйте немного для лучшего понимания).

Подождите()

  1. Метод wait() снимает блокировку.
  2. wait() - это метод класса Object.
  3. wait() - нестатический метод - public final void wait() throws InterruptedException {//...}
  4. wait() должен быть уведомлен notify() или notifyAll() методы.
  5. Метод wait() должен вызываться из цикла, чтобы справиться с ложной тревогой.

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

спать()

  1. Метод sleep() не снимает блокировку.
  2. sleep() - это метод класса java.lang.Thread.
  3. sleep() - статический метод - public static void sleep(long millis, int nanos) throws InterruptedException {//... }
  4. по истечении указанного времени sleep() завершен.
  5. sleep() лучше не вызывать из цикла (т.е. см. код ниже).
  6. sleep() может вызываться из любого места. нет особых требований.

Ссылка: разница между ожиданием и сном

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

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

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

Изображение 1367

  • 0
    Верно ли, что спящий поток может быть разбужен вызовами notify ()? Некоторые из других сообщений здесь, по-видимому, подразумевают, что спящая тема не может быть разбужена, но прервана.
  • 0
    Да, Thread.sleep() используется для того, чтобы сделать процессорное время доступным для других потоков. период ожидания может быть прерван прерываниями (т. е. JVM). Прочитайте это stackoverflow.com/questions/4264355/…
Показать ещё 4 комментария
29

Есть некоторые отличительные ключевые заметки, которые я заключил после работы в режиме ожидания и сна, сначала взгляните на образец, используя 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 get get (метод класса так влияет на текущий текущий поток)
  • Синхронное:
    • wait(): когда синхронизированный доступ к нескольким потокам один и тот же объект (HandObject) (когда требуется связь между несколькими потоками (выполнение выполнения потока, поток выполнить получение пива) на одном объекте HandObject)
    • sleep(): при ожидании условия продолжения выполнения (Доступен пиво ожидания)
  • Блокировка фиксации:
    • wait(): отпустите блокировку для другого объекта, чтобы иметь возможность выполнить (HandObject свободен, вы можете выполнять другое задание)
    • sleep(): удерживайте блокировку не менее чем в t раз (или до прерывания) (Моя работа еще не закончена, я продолжаю удерживать блокировку и жду некоторых условий для продолжения)
  • Состояние пробуждения:
    • wait(): до вызова notify(), notifyAll() из объекта
    • sleep(): до тех пор, пока не истечет время или прерывание вызова
  • И последний пункт используется, когда, поскольку estani указывает:

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

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

20

Разница между ожиданиями() и сном()

  • Принципиальное отличие состоит в том, что wait() - это Object а sleep() - статический метод Thread.

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

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

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

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

сходства

  • Обе заставляют текущий поток переходить в состояние Not Runnable.
  • Оба являются родными методами.
18

Это очень простой вопрос, потому что оба эти метода имеют совершенно другое применение.

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

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

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

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

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

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

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

Надеюсь, это поможет вам.

16

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

14

Ожидание и сон - это две разные вещи:

  • В sleep() поток прекращает работу в течение указанной продолжительности.
  • В wait() поток прекращает работу до тех пор, пока ожидаемый объект не будет уведомлен, как правило, другими потоками.
  • 0
    но вы можете прервать спящую нить. В этом случае wait () является избыточным, потому что он также теряет циклы процессора :-(
  • 9
    Подождите не тратить циклы процессора.
Показать ещё 5 комментариев
11

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

7

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:

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

Synchronized:

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

Hold lock:

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

Wake-up condition:

  • wait(): до вызова notify(), notifyAll() из объекта
  • sleep():, пока не истечет время или прерывание вызова().

Usage:

  • sleep(): для синхронизации времени и;
  • wait(): для многопоточной синхронизации.

Ссылка: diff sleep и wait

6

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

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

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

  • 2
    Но мы можем прервать сон, не так ли? так в чем же разница с этим сном / прерыванием против ожидания / уведомления?
  • 1
    Вы можете прервать спящего человека, но можете уведомить только ожидающего. Темы одинаковые.
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(), потоку не требуется блокировка объекта.

5

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

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

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

  • 1
    Зачем вам оба? Почему sleep () не достаточно?
  • 2
    Уведомление используется для связи между потоками. Чтобы вызвать wait, вам нужен какой-то объект, синхронизировать его, а затем вызвать wait на нем. Чтобы получить уведомление, вам нужен другой поток для синхронизации с тем же объектом и вызова notify.
4

сон

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

Wait

  • Он заставляет текущий поток ждать, пока другой поток не вызовет метод notify() или метод notifyAll() для этого объекта
  • Он должен вызываться из синхронного контекста, то есть из блока или method.It означает, что до вызова метода wait() текущий поток должен имеют блокировку на этом объекте.
  • Он освобождает блокировку объекта, на который он вызывается и добавляется в wait, так что другой поток может получить блокировку объекта.
4
  • wait() - метод класса Object.
    sleep() - метод класса Thread.

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

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

4

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

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

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

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

  • 0
    Так что, если поток спит в течение 10 секунд и происходит прерванное исключение ????
  • 0
    @Geek Возникает InterruptedException , как сказано в Javadoc.
Показать ещё 1 комментарий
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()   Когда он перейдет на стадию ожидания, его будет выпустить ключ и его ожидание некоторых секунд на основе параметра.

Пример:

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

ожидание(). когда вы откладываете и принимаете еще одно среднее, пока вы ждете, подождите [/p >

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

3

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

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 to, er, sleep, но тогда вам придется беспокоиться о блокировках.

Ни один из методов не использует процессор во время сна/ожидания.

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

Посмотрите сами: Доступен ли исходный код собственных методов? Файл /src/share/vm/prims/jvm.cpp является отправной точкой...

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

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

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

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

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

  • 4
    wait () не сохраняет процессор, обрабатывающий текущий поток. Это похоже на сон в том, что оно также вызывает переключение контекста: javamex.com/tutorials/threads/context_switch.shtml . Я просил пол года вокруг stackoverflow, и кажется, что никто не знает, в чем разница между wait / notify и sleep / interrupt.
  • 0
    хотя спящий режим не удерживает процессор в обработке текущего потока, я думаю, в любом случае это немного обременительно для ЦП, поскольку ЦП необходимо отслеживать момент, когда закончить спящий режим. У него нет такого внешнего триггера, как "notify" в ожидании. Нет?
2

От страницы документации оракала 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() (метод класса).

2

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

Для более Ссылка

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

Пример о сне не освобождает блокировку и ждет

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

  • Основной. Содержит основной метод и два потока.
  • 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.

2

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

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

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

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

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

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

2

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

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

1

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

1

Собственно, все это четко описано в документах Java (но я понял это только после прочтения ответов).

http://docs.oracle.com/javase/8/docs/api/index.html:

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

sleep() - Заставляет текущий исполняемый поток спать (временно прекратить выполнение) за указанное количество миллисекунд, с учетом точности и точности системных таймеров и планировщиков. Нить не теряет права собственности на какие-либо мониторы.

1
  • Метод wait(1000) заставляет текущий поток спать до одной секунды.
    • Нить может спать менее 1 секунды, если она получает notify() или notifyAll() вызов метода.
  • Вызов sleep(1000) заставляет текущий поток спать за ровно 1 секунду.
    • Также спальный поток не содержит блокировки любого ресурса. Но ожидающая нить делает.
  • 1
    sleep(1000) не гарантирует спать ровно 1 секунду. Это может быть прервано раньше.
  • 1
    Эти посты так запутаны. Все остальные сообщения в этой теме говорят, что спящий поток удерживает блокировку, а ожидающий поток не удерживает блокировку. Точно так же сообщение с диаграммой подразумевает, что вызовы notify () пробуждают спящие потоки, но другие сообщения (и диаграммы состояния потока) подразумевают, что это делает только interrupt () или время ожидания. Я просто заказал себе копию java-параллелизма на практике, что я должен был прочитать давным-давно!
Показать ещё 1 комментарий
1

wait() задается внутри синхронизированного метода тогда как sleep() задается внутри несинхронизированного метода, потому что метод wait() освобождает блокировку объекта, но sleep() или yield() освобождает lock().

  • 0
    sleep() может быть внутри synchronized блока или метода. Ответ ничего не объясняет.
0

Предположим, что вы слышите песни.

Пока текущая песня работает, следующая песня не будет воспроизводиться, т.е. Sleep() вызывается следующей песней

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

В обоих случаях песни идут в состояния Wait.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню