Спецификация Java 11: 17.2. Набор ожиданий и уведомления
Каждый объект, помимо связанного монитора, имеет связанный набор ожиданий (wait set). Набор ожиданий - это набор потоков.
Когда объект создается впервые, его набор ожидания пуст. Элементарные действия, которые добавляют потоки и удаляют потоки из наборов ожидания, являются атомарными. Наборы ожидания управляются исключительно с помощью методов Object.wait, Object.notify и Object.notifyAll.
На манипуляции с наборами ожидания также может влиять статус прерывания потока и методы класса Thread, работающие с прерыванием. Кроме того, методы класса Thread для сна и присоединения к другим потокам имеют свойства, производные от свойств ожидания и уведомлений.
17.2.1. Ожидание (wait)
Действия ожидания происходят при вызове метода wait() или форм wait(long millisecs) и wait(long millisecs, int nanosecs).
Вызов wait(long millisecs) с нулевым параметром или вызов wait(long millisecs, int nanosecs) с двумя нулевыми параметрами эквивалентен вызову wait().
Поток нормально возвращается из ожидания, если он возвращается без исключения InterruptedException.
Пусть поток t будет потоком, выполняющим метод wait для объекта m, и пусть n будет количеством действий блокировки t на m, которые не были сопоставлены действиями разблокировки. Происходит одно из следующих действий:
- Если n равно нулю (т. е. поток t еще не имеет блокировки для цели m), то генерируется исключение IllegalMonitorStateException.
- Если это wait с временем и аргумент nanosecs не находится в диапазоне 0-999999 или аргумент millisecs отрицательный, возникает исключение IllegalArgumentException.
- Если поток t прерывается, возникает исключение InterruptedException, а статус прерывания t устанавливается в значение false.
- В противном случае имеет место следующая последовательность:
- Поток t добавляется в набор ожидания объекта m и выполняет n действий разблокировки на m.
-
Поток t не выполняет никаких дальнейших инструкций, пока он не будет удален из набора ожидания m. Поток может быть удален из набора ожидания из-за любого из следующих действий и возобновится через некоторое время:
- Действие уведомления (notify), выполняемое на m, в котором t выбрано для удаления из набора ожидания.
- Действие notifyAll, выполняемое на m.
- Прерывание (interrupt) выполняется на t.
- Если это wait с временем ожидания, внутреннее действие, удаляющее t из набора ожидания m, которое происходит по истечении, по крайней мере, millisecs миллисекунд плюс nanosecs наносекунд с начала этого действия ожидания.
-
Внутреннее действие реализации. Реализациям разрешено, хотя и не рекомендуется, выполнять "ложные пробуждения", то есть удалять потоки из наборов ожидания и, таким образом, разрешать возобновление без явных инструкций для этого.
Обратите внимание, что это положение требует практики кодирования Java с использованием wait только внутри циклов, которые завершаются только тогда, когда выполняется какое-то логическое условие, которого ожидает поток.
Каждый поток должен определять порядок событий, которые могут привести к его удалению из набора ожидания. Этот порядок не обязательно должен соответствовать другим порядкам, но поток должен вести себя так, как если бы эти события произошли в этом порядке.
Например, если поток t находится в наборе ожидания для m, а затем происходит как прерывание t, так и уведомление m, должен быть порядок этих событий. Если считается, что прерывание произошло первым, тогда t в конечном итоге вернется из ожидания, выбрасывая InterruptedException, и какой-то другой поток в ожидании, установленном для m (если таковой существует на момент уведомления), должен получить уведомление. Если считается, что уведомление появилось первым, то в конечном итоге t вернется в обычном режиме из ожидания с ожидающим прерыванием.
- Поток t выполняет n действий блокировки на m.
- Если поток t был удален из набора ожидания m на шаге 2 из-за прерывания, тогда состояние прерывания t устанавливается в false, и метод ожидания генерирует InterruptedException.
Читайте также:
- Спецификация Java 11: 9.8. Функциональные интерфейсы
- Спецификация Java 11: Глава 17. Потоки и блокировки
- Спецификация Java 11: 17.1. Синхронизация
Комментарии
Отправить комментарий