Вопрос

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

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

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

Это было полезно?

Решение

A wait можно "разбудить" другим потоком, вызывающим уведомить на ожидаемом мониторе, тогда как sleep не может. Также wait notify ) должно происходить в блоке synchronized на объекте монитора, тогда как sleep этого не делает:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 

В этот момент исполняемый поток ожидает и освобождает монитор . Другой поток может сделать

synchronized (mon) { mon.notify(); }

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

Вы также можете вызвать notifyAll , если на мониторе ожидает более одного потока & # 8211; это разбудит их всех . Однако только один из потоков сможет захватить монитор (помните, что wait находится в блоке synchronized ) и продолжить & # 8211; остальные будут заблокированы, пока они не получат блокировку монитора.

Другой момент заключается в том, что вы вызываете wait на Object (т.е. вы ждете на мониторе объекта), тогда как вы вызываете sleep для Тема .

Еще один момент заключается в том, что вы можете получить ложные пробуждения из 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 () снимает блокировку.
  • wait () - это метод класса Object .
  • wait () - нестатический метод - public final void wait () генерирует InterruptedException {// ...}
  • wait () должен быть уведомлен методами notify () или notifyAll () .
  • Метод
  • wait () необходимо вызывать из цикла, чтобы справиться с ложной тревогой.

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

  • sleep ()

    <Ол> Метод
  • sleep () не снимает блокировку.
  • sleep () - это метод класса java.lang.Thread .
  • sleep () - статический метод - public static void sleep (long millis, int nanos) выдает InterruptedException {// ...}
  • по истечении указанного промежутка времени, sleep () завершен.
  • sleep () лучше не вызывать из цикла (т. е. см. код ниже ).
  • sleep () может вызываться откуда угодно. нет конкретных требований.
  • Ссылка: Разница между ожиданием и сном

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

    synchronized(monitor){
        while(condition == true){ 
            monitor.wait()  //releases monitor lock
        }
    
        Thread.sleep(100); //puts current thread on Sleep    
    }
    

     переход потока в разные состояния потока

    Есть некоторые ключевые замечания о различиях, которые я завершаю после работы над wait и sleep, сначала взгляните на образец, используя wait() и sleep ():

    Пример 1:используя подожди() и спать():

    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();
    }
    

    Давайте внесем ясность в некоторые ключевые замечания:

    1. Звонить по:
      • ждать():Вызовите текущий поток, содержащий объект HandObject
      • спать():Вызов в потоке execute task get beer (метод класса так влияет на текущий запущенный поток)
    2. Синхронизированный:
      • ждать():при синхронизированном многопоточном доступе к одному и тому же объекту (HandObject) (Когда требуется связь между несколькими потоками (поток выполняет кодирование, поток выполняет получение пива), доступ к одному и тому же объекту HandObject)
      • спать():при выполнении условия ожидания продолжения выполнения (доступно ожидающее пиво)
    3. Удерживать замок:
      • ждать():снимите блокировку для другого объекта, имеющего возможность выполнить (HandObject свободен, вы можете выполнять другую работу)
      • спать():держите блокировку как минимум t раз (или до прерывания) (моя работа все еще не завершена, я продолжаю удерживать блокировку и жду продолжения выполнения некоторого условия)
    4. Состояние пробуждения:
      • ждать():пока не вызовем notify(), notifyAll() из объекта
      • спать():по крайней мере до истечения времени или прерывания вызова
    5. И последний момент таков используйте, когда как эстани указывать:

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

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

    Разница между wait() и sleep()

    • Принципиальное различие заключается в том, что wait() находится от Object и sleep() является статическим методом Thread.

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

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

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

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

    Сходства

    • Оба заставляют текущий поток переходить в Не Поддается запуску государство.
    • И то, и другое таково родной методы.

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

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

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

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

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

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

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

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

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

    источник: http://www.jguru.com/faq/view. JSP? EID = 47127

      

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

         

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

         

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

         

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

    Ждать и спать - это две разные вещи:

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

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

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

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

    Поток.sleep() отправляет текущий поток в состояние “Не выполняется” на некоторое время.Поток сохраняет приобретенные им мониторы, т. е.если поток в данный момент находится в синхронизированном блоке или методе, никакой другой поток не может войти в этот блок или метод.Если другой поток вызовет функцию t.interrupt(), это разбудит спящий поток.Обратите внимание, что sleep - это статический метод, что означает, что он всегда влияет на текущий поток (тот, который выполняет метод sleep).Распространенной ошибкой является вызов t.sleep(), где t - другой поток;даже в этом случае это текущий поток, который будет находиться в режиме ожидания, а не t-поток.

    object.wait() объект.ждать() отправляет текущий поток в состояние “Не выполняется”, как sleep(), но с изюминкой.Wait вызывается для объекта, а не для потока;мы называем этот объект “объектом блокировки”. Перед вызовом 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() из объекта
    • спать(): по крайней мере, до истечения времени или вызова функции interrupt().

    Usage:

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

    Ссылка:разница sleep и wait

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

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

    Если подумать, то названия в этом отношении сбивают с толку;однако sleep является стандартным именем и wait это похоже на WaitForSingleObject или WaitForMultipleObjects в Win API.

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

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

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

    Из этого поста: http://javaconceptoftheday.com / разница между ними, поживем-сна-методы-в-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 () поток не должен иметь объектную блокировку.

    <Ол>
  • wait () - это метод класса Object .
    sleep () - это метод класса Thread .

  • sleep () позволяет потоку переходить в состояние sleep в течение x миллисекунд.
    Когда поток переходит в состояние сна , он не снимает блокировку .

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

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

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

    Вы правы - 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 () будет некоторое время ... после этого он автоматически перейдет в состояние готовности ...

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

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

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

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

    Метод

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

    Метод

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

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

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

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

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

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

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

    Пример о том, что sleep не снимает блокировку, а wait снимает

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

    1. Главная :Содержит основной метод и два потока.
    2. Синглтон :Это одноэлементный класс с двумя статическими методами 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 не снимет блокировку.

    Теперь измените синглтон.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 запустился со своей последней позиции и создал еще один одноэлементный объект.

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

    IllegalMonitorStateException: , если метод wait () вызывается без получения блокировки объекта, тогда IllegalMonitorStateException генерируется во время выполнения, но sleep ( ) никогда не генерирует такое исключение.

    Принадлежит к какому классу: wait () принадлежит классу java.lang.Object , но sleep () принадлежит классу java.lang.Thread .

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

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

    При вызове из синхронизированного блока: , когда вызывается метод wait () , поток покидает блокировку объекта. Но метод sleep () при вызове из синхронизированного блока или потока метода не оставляет объектную блокировку.

    Для получения дополнительной информации Справка

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

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

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

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

  • Со страницы документации оракула на Метод sleep () класса Thread :

    public static void sleep(long millis)
    
    <Ол>
  • Заставляет текущий выполняющийся поток спать (временно прекращать выполнение) на указанное количество миллисекунд, в зависимости от точности и точности системных таймеров и планировщиков.
  • Поток не теряет права собственности ни на какие мониторы.
  • Этот метод выдает:

    <Ол>
  • IllegalArgumentException - если значение millis отрицательное

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

  • Другое ключевое отличие:

    wait () - это нестатический метод (метод экземпляра) в отличие от статического метода sleep () (метод класса).

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

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

    • Способ wait(1000) переводит текущий поток в спящий режим до одной секунды.
      • Поток может находиться в режиме ожидания менее 1 секунды, если он получит notify() или notifyAll() вызов метода.
    • Призыв к sleep(1000) переводит текущий поток в спящий режим на ровно 1 секунда.
      • Также спящий поток не содержит блокировки ни одного ресурса.Но ожидающий поток делает это.
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top