Класс выбора
- Все реализуемые интерфейсы:
-
Closeable,AutoCloseable
- Непосредственные известные подклассы:
AbstractSelector
public abstract class Selector extends Object implements Closeable
SelectableChannel. Выборщик можно создать, вызвав метод open этого класса, который будет использовать системный по умолчанию selector provider для создания нового выборщика. Выборщик также можно создать, вызвав метод openSelector пользовательского поставщика выборщиков. Выборщик остаётся открытым до тех пор, пока он не будет закрыт с помощью метода close.
Регистрация канала, подлежащего выбору, с выборщиком представлена объектом SelectionKey. Выборщик хранит три набора ключей выбора:
Множество ключей содержит ключи, представляющие текущие регистрации каналов этого выборщика. Этот набор возвращается методом
keys.Множество выбранных ключей представляет собой множество ключей, для канала каждого из которых было обнаружено, что он готов к по крайней мере одной из операций, определённых в наборе интересов ключа во время предыдущей операции выбора, которая добавляет ключи или обновляет ключи в наборе. Этот набор возвращается методом
selectedKeys. Множество выбранных ключей всегда является подмножеством множества ключей.Множество отменённых ключей — это множество ключей, которые были отменены, но каналы которых ещё не были дерегистрированы. К этому набору нет прямого доступа. Множество отменённых ключей всегда является подмножеством множества ключей.
Все три набора пустые в только что созданном выборщике.
Ключ добавляется в множество ключей выборщика в качестве побочного эффекта регистрации канала через метод register канала. Отменённые ключи удаляются из множества ключей во время операций выбора. Само множество ключей не может быть изменено напрямую.
Ключ добавляется в множество отменённых ключей выборщика, когда он отменяется, будь то путём закрытия канала или вызова метода cancel. Отмена ключа приведёт к дерегистрации его канала во время следующей операции выбора, в этот момент ключ будет удалён из всех множеств ключей выборщика.
Ключи добавляются в множество выбранных ключей путём операций выбора. Ключ можно удалить напрямую из множества выбранных ключей, вызвав метод remove набора или вызвав метод remove итератора, полученного из набора. Все ключи можно удалить из множества выбранных ключей, вызвав метод clear набора. Ключи нельзя добавить непосредственно в множество выбранных ключей.
Выбор
Операция выбора запрашивает у базовой операционной системы обновление о готовности каждого зарегистрированного канала выполнить любую из операций, определённых набором интересов его ключа. Существует две формы операций выбора:
Методы
select(),select(long)иselectNow()добавляют ключи каналов, готовых выполнить операцию, в множество выбранных ключей или обновляют множество готовых операций для ключей, уже находящихся в множестве выбранных ключей.Методы
select(Consumer),select(Consumer, long)иselectNow(Consumer)выполняют действие над ключом каждого канала, готового выполнить операцию. Эти методы не добавляют в множество выбранных ключей.
Операции выбора, добавляющие в множество выбранных ключей
Во время каждой операции выбора ключи могут добавляться и удаляться из множества выбранных ключей и из множеств ключей и отменённых ключей выборщика. Выбор выполняется методами select(), select(long) и selectNow() и включает три шага:
Каждый ключ из множества отменённых ключей удаляется из каждого набора ключей, членом которого он является, и его канал дерегистрируется. Этот шаг оставляет множество отменённых ключей пустым.
-
Базовая операционная система запрашивает обновление о готовности каждого оставшегося канала выполнить любую из операций, определённых набором интересов его ключа на момент начала операции выбора. Для канала, готового к по крайней мере одной такой операции, выполняется одно из следующих двух действий:
Если ключ канала ещё не находится в множестве выбранных ключей, то он добавляется в этот набор, а его набор готовых операций изменяется, чтобы идентифицировать именно те операции, для которых канал теперь готов. Любая информация о готовности, ранее записанная в наборе, отбрасывается.
В противном случае ключ канала уже находится в множестве выбранных ключей, поэтому его набор готовых операций изменяется, чтобы идентифицировать любые новые операции, для которых канал готов. Любая информация о готовности, ранее записанная в наборе, сохраняется; другими словами, набор готовности, возвращённый базовой системой, объединяется поразрядно с текущим набором готовых операций ключа.
Если в процессе шага (2) были добавлены какие-либо ключи в множество отменённых ключей, то они обрабатываются как в шаге (1).
Единственным существенным различием между тремя методами выбора является то, блокируется ли операция выбора для ожидания готовности одного или нескольких каналов, и если да, то на какое время.
Операции выбора, выполняющие действие над выбранными ключами
Во время каждой операции выбора ключи могут быть удалены из набора ключей, набора выбранных ключей и набора отменённых ключей выборщика. Выбор выполняется методами select(Consumer), select(Consumer,long) и selectNow(Consumer) и включает три шага:
Каждый ключ из множества отменённых ключей удаляется из каждого набора ключей, членом которого он является, и его канал дерегистрируется. Этот шаг оставляет множество отменённых ключей пустым.
-
Базовая операционная система запрашивает обновление о готовности каждого оставшегося канала выполнить любую из операций, определённых набором интересов его ключа на момент начала операции выбора.
Для канала, готового к по крайней мере одной такой операции, набор готовых операций ключа канала устанавливается так, чтобы идентифицировать именно те операции, для которых канал готов, и вызывается действие, указанное методу
select, для потребления ключа канала. Любая информация о готовности, ранее записанная в наборе, отбрасывается перед вызовом действия.В качестве альтернативы, если канал готов к более чем одной операции, действие может быть вызвано более одного раза с ключом канала и набором готовых операций, изменённым на подмножество операций, для которых канал готов. Если действие вызывается более одного раза для одного ключа, то его набор готовых операций никогда не содержит биты операций, которые содержались в наборе при предыдущих вызовах действия в одной и той же операции выбора.
Если в процессе шага (2) были добавлены какие-либо ключи в множество отменённых ключей, то они обрабатываются как в шаге (1).
Конкурентность
Выборщик и его множество ключей безопасны для использования несколькими потоками. Однако множество выбранных ключей и множество отменённых ключей не безопасны.
Операции выбора синхронизируются на самом выборщике, а затем на множестве выбранных ключей. Они также синхронизируются на множестве отменённых ключей на шагах (1) и (3) выше.
Изменения, внесённые в наборы интересов ключей выборщика во время выполнения операции выбора, не оказывают никакого влияния на эту операцию; они будут видны следующей операцией выбора.
Ключи могут быть отменены, и каналы могут быть закрыты в любое время. Следовательно, наличие ключа в одном или нескольких множествах ключей выборщика не означает, что ключ действителен или что его канал открыт. Приложение должно тщательно синхронизироваться и проверять эти условия по мере необходимости, если существует возможность того, что другой поток отменит ключ или закроет канал.
Блокированный в операции выбора поток может быть прерван другим потоком тремя способами:
Вызвать метод
wakeupвыборщика,Вызвать метод
closeвыборщика, илиВызвать метод
interruptзаблокированного потока, в этом случае его статус прерывания будет установлен, и вызывается методwakeupвыборщика.
Метод close синхронизируется на выборщике и его множестве выбранных ключей в том же порядке, что и в операции выбора.
Множество ключей выборщика безопасно для использования несколькими потоками. Операции извлечения из множества ключей обычно не блокируются и поэтому могут перекрываться с новыми регистрациями, которые добавляют в множество, или с шагами отмены операций выбора, которые удаляют ключи из множества. Итераторы и разделители возвращают элементы, отражающие состояние набора в какой-то момент времени, начиная с момента создания итератора/разделителя. Они не выбрасывают исключение ConcurrentModificationException.
Множество выбранных ключей выборщика обычно не безопасно для использования несколькими потоками. Если такой поток может напрямую изменить набор, то доступ должен контролироваться путём синхронизации на самом наборе. Итераторы, возвращаемые методами iterator набора, являются быстродействующими: если набор изменяется после создания итератора, любым способом, кроме вызова метода remove самого итератора, то будет брошено исключение ConcurrentModificationException.
- Since:
- 1.4
- See Also:
Краткое описание конструкторов
| Modifier | Конструктор | Описание |
|---|---|---|
protected |
Инициализирует новый экземпляр этого класса. |
Краткое описание методов
| Modifier and Type | Метод | Описание |
|---|---|---|
abstract void |
close() |
Закрывает этот селектор. |
abstract boolean |
isOpen() |
Указывает, открыт ли этот селектор. |
abstract Set<SelectionKey> |
keys() |
Возвращает набор ключей этого селектора. |
static Selector |
open() |
Открывает селектор. |
abstract SelectorProvider |
provider() |
Возвращает поставщика, который создал этот канал. |
abstract int |
select() |
Выбирает набор ключей, соответствующие каналы которых готовы к операциям ввода-вывода. |
abstract int |
select |
Выбирает набор ключей, соответствующие каналы которых готовы к операциям ввода-вывода. |
int |
select |
Выбирает и выполняет действие над ключами, соответствующие каналы которых готовы к операциям ввода-вывода. |
int |
select |
Выбирает и выполняет действие над ключами, соответствующие каналы которых готовы к операциям ввода-вывода. |
abstract Set<SelectionKey> |
selectedKeys() |
Возвращает набор выбранных ключей этого селектора. |
abstract int |
selectNow() |
Выбирает набор ключей, соответствующие каналы которых готовы к операциям ввода-вывода. |
int |
selectNow |
Выбирает и выполняет действие над ключами, соответствующие каналы которых готовы к операциям ввода-вывода. |
abstract Selector |
wakeup() |
Заставляет первую операцию выбора, которая еще не возвратила результат, возвратиться немедленно. |
Подробное описание конструкторов
Конструктор
protected Selector()
Подробное описание методов
open
public static Selector open() throws IOException
Новый селектор создается путем вызова метода openSelector системного объекта по умолчанию SelectorProvider.
- Возвращает:
- Новый селектор
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода
isOpen
public abstract boolean isOpen()
- Возвращает:
-
trueесли, и только если, селектор открыт
provider
public abstract SelectorProvider provider()
- Возвращает:
- Провайдер, который создал этот канал
keys
public abstract Set<SelectionKey> keys()
Набор ключей не может быть напрямую изменен. Ключ удаляется только после его отмены и дерегистрации соответствующего канала. Любая попытка изменить набор ключей приведет к броску исключения UnsupportedOperationException.
Набор является безопасным для использования несколькими потоками.
- Возвращает:
- Набор ключей селектора
- Изначает:
-
ClosedSelectorException- Если селектор закрыт
selectedKeys
public abstract Set<SelectionKey> selectedKeys()
Ключи могут быть удалены из набора выбранных ключей, но не могут быть добавлены напрямую. Любая попытка добавить объект в набор ключей приведет к броску исключения UnsupportedOperationException.
Набор выбранных ключей не потокобезопасен.
- Возвращает:
- Набор выбранных ключей селектора
- Изначает:
-
ClosedSelectorException- Если селектор закрыт
selectNow
public abstract int selectNow() throws IOException
Этот метод выполняет операцию выбора без блокировки. Если ни один канал не стал селектируемым с момента предыдущей операции выбора, этот метод сразу возвращает ноль.
Вызов этого метода очищает эффект любых предыдущих вызовов метода wakeup.
- Возвращает:
- Количество ключей, возможно ноль, наборы операций которых были обновлены операцией выбора
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода -
ClosedSelectorException- Если селектор закрыт
select
public abstract int select(long timeout) throws IOException
Этот метод выполняет блокирующую операцию выбора. Он возвращает только после того, как хотя бы один канал выбран, метод wakeup этого селектора вызван, текущий поток прерван или истек заданный таймаут, в зависимости от того, что произойдет раньше.
Этот метод не обеспечивает гарантий реального времени: он планирует таймаут так, как если бы был вызван метод Object.wait(long).
- Параметры:
-
timeout- Если положительное, заблокировать доtimeoutмиллисекунд, более или менее, ожидая, пока канал станет готовым; если ноль, заблокировать неопределенно; не должно быть отрицательным - Возвращает:
- Количество ключей, возможно ноль, наборы операций которых были обновлены
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода -
ClosedSelectorException- Если селектор закрыт -
IllegalArgumentException- Если значение аргумента таймаута отрицательно
select
public abstract int select() throws IOException
Этот метод выполняет блокирующую операцию выбора. Он возвращает только после того, как хотя бы один канал выбран, метод wakeup этого селектора вызван или текущий поток прерван, в зависимости от того, что произойдет раньше.
- Возвращает:
- Количество ключей, возможно ноль, наборы операций которых были обновлены
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода -
ClosedSelectorException- Если селектор закрыт
select
public int select(Consumer<SelectionKey> action, long timeout) throws IOException
Этот метод выполняет блокирующую операцию выбора. Он пробуждается от запроса к операционной системе только тогда, когда выбран хотя бы один канал, вызван метод wakeup этого селектора, текущий поток прерван или истек заданный таймаут, в зависимости от того, что произойдет раньше.
Указанный метод action's accept вызывается с ключом для каждого канала, который готов выполнить операцию, идентифицируемую набором интересов ключа. Метод accept может быть вызван более одного раза для одного ключа, но с набором готовых операций, содержащим подмножество операций, для которых канал готов (как описано выше). Метод accept вызывается, будучи синхронизированным на селекторе и его наборе выбранных ключей. Необходимо проявлять особую осторожность, чтобы избежать тупика с другими потоками, которые также синхронизируются на этих объектах. Операции выбора не являются реентерабельными в целом, и поэтому действие должно быть очень осторожным, чтобы не пытаться выполнить операцию выбора на том же селекторе. Поведение при попытке реентерабельной операции выбора зависит от реализации и поэтому не специфицируется. Если действие закрывает селектор, то ClosedSelectorException выбрасывается, когда действие завершается. Действие не запрещено закрывать каналы, зарегистрированные с селектором, или отменять ключи или изменять набор интересов ключа. Если канал выбран, но его ключ отменен или его набор интересов изменен до выполнения действия над ключом, то поведение зависит от реализации относительно того, будет ли вызвано действие (возможно, с ключом invalid). Исключение, выброшенное действием, передается вызывающему потоку.
Этот метод не обеспечивает гарантий реального времени: он планирует таймаут так, как если бы был вызван метод Object.wait(long).
- Требования к реализации:
- По умолчанию, реализация удаляет все ключи из набора выбранных ключей, вызывает
select(long)с указанным таймаутом, а затем выполняет действие для каждого ключа, добавленного в набор выбранных ключей. По умолчанию, реализация не обнаруживает действие, выполняющее реентерабельный выбор. - Параметры:
-
action- Действие, которое необходимо выполнить -
timeout- Если положительное, заблокировать доtimeoutмиллисекунд, более или менее, ожидая, пока канал станет готовым; если ноль, заблокировать неопределенно; не должно быть отрицательным - Возвращает:
- Количество уникальных ключей, которые были использованы, возможно ноль
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода -
ClosedSelectorException- Если этот селектор закрыт или закрыт действием -
IllegalArgumentException- Если значение аргумента таймаута отрицательное - С:
- 11
select
public int select(Consumer<SelectionKey> action) throws IOException
Этот метод выполняет блокирующую операцию выбора. Он пробуждается от запроса к операционной системе только тогда, когда выбран хотя бы один канал, вызван метод wakeup этого селектора или текущий поток прерван, в зависимости от того, что произойдет раньше.
Этот метод эквивалентен вызову метода с двумя аргументами select с таймаутом 0 для неопределенного ожидания.
- Требования к реализации:
- По умолчанию, реализация вызывает метод
selectс двумя аргументами с таймаутом0. - Параметры:
-
action- Действие, которое необходимо выполнить - Возвращает:
- Количество уникальных ключей, которые были использованы, возможно ноль
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода -
ClosedSelectorException- Если этот селектор закрыт или закрыт действием - С:
- 11
selectNow
public int selectNow(Consumer<SelectionKey> action) throws IOException
Этот метод выполняет операцию выбора без блокировки.
Вызов этого метода очищает эффект любых предыдущих вызовов метода wakeup.
- Требования к реализации:
- По умолчанию, реализация удаляет все ключи из набора выбранных ключей, вызывает
selectNow()и затем выполняет действие для каждого ключа, добавленного в набор выбранных ключей. По умолчанию, реализация не обнаруживает действие, выполняющее реентерабельный выбор. Набор выбранных ключей может быть пустым или не пустым по завершении реализации по умолчанию. - Параметры:
-
action- Действие, которое необходимо выполнить - Возвращает:
- Количество уникальных ключей, которые были использованы, возможно ноль
- Изначает:
-
IOException- Если произошла ошибка ввода-вывода -
ClosedSelectorException- Если этот селектор закрыт или закрыт действием - С:
- 11
wakeup
public abstract Selector wakeup()
Если другой поток в настоящее время заблокирован в операции выбора, то это вызов вернётся немедленно. Если в данный момент не происходит никакой операции выбора, то следующий вызов операции выбора вернётся немедленно, если при этом не был вызван selectNow() или selectNow(Consumer). В любом случае, значение, возвращаемое этим вызовом, может быть отличным от нуля. Последующие операции выбора будут заблокированы как обычно, если этот метод не будет вызван вновь в промежутке.
Вызов этого метода более одного раза между двумя последовательными операциями выбора имеет тот же эффект, что и вызов его только один раз.
- Returns:
- Этот селектор
close
public abstract void close() throws IOException
Если поток в данный момент заблокирован в одном из методов выбора этого селектора, то он прерывается так, как если бы был вызван метод селектора wakeup.
Все ещё не отменённые ключи, связанные с этим селектором, становятся недействительными, их каналы аннулируются, и все другие ресурсы, связанные с этим селектором, освобождаются.
Если этот селектор уже закрыт, то вызов этого метода не оказывает никакого эффекта.
После закрытия селектора любая дальнейшая попытка использовать его, кроме как вызовом этого метода или метода wakeup, приведёт к тому, что будет брошено исключение ClosedSelectorException.
- Specified by:
-
closeв интерфейсеAutoCloseable - Specified by:
-
closeв интерфейсеCloseable - Throws:
-
IOException- Если произошла ошибка ввода-вывода
© 1993, 2021, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/nio/channels/Selector.html