- java.lang.Object
-
- java.nio.channels.Selector
-
- All Implemented Interfaces:
-
Closeable
,AutoCloseable
- 已知直接子类:
-
AbstractSelector
public abstract class Selector extends Object implements Closeable
SelectableChannel
对象的多路复用器。可以通过调用此类的
open
方法来创建一个选择器,该方法将使用系统的默认值selector provider
创建一个新的选择器。 还可以通过调用自定义选择器提供程序的openSelector
方法来创建选择器。 选择器保持打开,直到通过其close
方法关闭。可选频道对选择器的注册由
SelectionKey
对象表示。 选择器保存三组选择键:密钥集包含表示此选择器当前通道注册的键。 此集由
keys
方法返回。所选择的密钥集是一组密钥,使得每个密钥的信道被检测为在先前选择操作期间的密钥的兴趣集中识别的至少一个操作准备好。 该集合由
selectedKeys
方法返回。 所选密钥集始终是密钥集的子集。取消的密钥集是已经被取消但其通道尚未被注销的密钥的集合。 此集不能直接访问。 取消的密钥集始终是密钥集的子集。
新创建的选择器中的所有三组都为空。
通过频道的
register
方法,将密钥添加到选择器的密钥集中,作为注册频道的副作用 。 在选择操作期间,从键集中删除取消的键。 密钥集本身不能直接修改。无论是通过关闭其频道还是通过调用其
cancel
方法,钥匙将被取消,将其添加到选择器取消的钥匙组中。 取消键将导致其通道在下一次选择操作期间被取消注册,此时该键将从所有选择器的键集中移除。键通过选择操作被添加到所选择的键集中。 一个关键的可直接从通过调用该组的设定的选择键被移除
remove
方法或通过调用remove
一个的方法iterator
从集合获得的。 密钥永远不会以任何其他方式从所选密钥集中删除; 特别是作为选择操作的副作用而不被删除。 键可能不会直接添加到选定的键集。选择
在每个选择操作期间,键可以被添加到选择器的选择键集合并从其中移除,并且可以从其键和取消的键集合中移除。 选择由执行
select()
,select(long)
,并selectNow()
方法,以及包括三个步骤:取消密钥集中的每个密钥从其作为其成员的每个密钥集中移除,并且其信道被注销。 此步骤将取消的密钥设置为空。
查询底层操作系统,以便更新每个剩余通道的准备状态,以便在选择操作开始的时刻执行由其密钥的兴趣集确定的任何操作。 对于准备进行至少一个此类操作的通道,执行以下两个操作之一:
如果频道的密钥尚未在选择的密钥集中,则将其添加到该集合中,并且其即时操作集被修改,以便准确地标识该信道现在被报告准备好的那些操作。 先前记录在就绪集中的任何就绪信息被丢弃。
否则,频道的密钥已经在选择密钥集中,因此其即时操作集被修改,以识别通道报告准备就绪的任何新操作。 以前记录在就绪集中的任何准备信息都将被保留; 换句话说,由底层系统返回的准备集被按位分离到键的当前准备集中。
如果在步骤(2)进行中将任何键添加到取消的键集合,则它们将如步骤(1)中那样处理。
选择操作是否阻止等待一个或多个通道准备就绪,如果是这样,多长时间是三种选择方法之间唯一的本质区别。
并发
选择器本身可以安全地被多个并发线程使用; 不过,他们的钥匙不是。
选择操作在选择器本身,按键集合和所选键集上以该顺序同步。 它们还在上述步骤(1)和(3)中的取消键集上进行同步。
在选择操作正在进行时,对选择器的键的兴趣集进行的更改对该操作没有影响; 他们将在下一个选择操作中看到。
钥匙可能会被取消,渠道可能随时关闭。 因此,在一个或多个选择器的密钥组中存在密钥并不意味着密钥是有效的或其信道是打开的。 如果有可能另一个线程将取消键或关闭通道,应用程序代码应小心同步并根据需要检查这些条件。
在其中一个
select()
或select(long)
方法中阻塞的线程可能会被其他线程以三种方式之一中断:close
方法以与选择操作相同的顺序在选择器和所有三个按键组上同步。选择器的密钥和选择密钥集合通常不会被多个并发线程安全使用。 如果这样的线程可以直接修改这些集合中的一个,则应该通过对集合本身进行同步来控制访问。 这些集合'
iterator
方法返回的迭代器是故障快速的:如果在迭代器创建之后修改集合,除了通过调用迭代器自己的remove
方法之外,以任何方式都将被修改, 因此将抛出一个ConcurrentModificationException
。- 从以下版本开始:
- 1.4
- 另请参见:
-
SelectableChannel
,SelectionKey
-
-
构造方法摘要
构造方法 Modifier Constructor 描述 protected
Selector()
初始化此类的新实例。
-
方法摘要
所有方法 静态方法 接口方法 抽象方法 具体的方法 Modifier and Type 方法 描述 abstract void
close()
关闭此选择器。abstract boolean
isOpen()
告诉这个选择器是否打开。abstract Set<SelectionKey>
keys()
返回此选择器的键集。static Selector
open()
打开选择器。abstract SelectorProvider
provider()
返回创建此通道的提供程序。abstract int
select()
选择一组其相应通道准备好进行I / O操作的键。abstract int
select(long timeout)
选择一组其相应通道准备好进行I / O操作的键。abstract Set<SelectionKey>
selectedKeys()
返回此选择器的选择键集。abstract int
selectNow()
选择一组其相应通道准备好进行I / O操作的键。abstract Selector
wakeup()
导致尚未返回的第一个选择操作立即返回。
-
-
-
方法详细信息
-
open
public static Selector open() throws IOException
打开选择器。新的选择器是通过调用系统范围默认的
SelectorProvider
对象的openSelector
方法来创建的。- 结果
- 一个新的选择器
- 异常
-
IOException
- 如果发生I / O错误
-
isOpen
public abstract boolean isOpen()
告诉这个选择器是否打开。- 结果
-
true
如果,并且只有这个选择器是打开的
-
provider
public abstract SelectorProvider provider()
返回创建此通道的提供程序。- 结果
- 创建此频道的提供商
-
keys
public abstract Set<SelectionKey> keys()
返回此选择器的键集。密钥集不能直接修改。 一旦钥匙被取消并且其通道已被注销,该钥匙将被移除。 任何修改密钥集的尝试将导致抛出
UnsupportedOperationException
。钥匙组为not thread-safe 。
- 结果
- 这个选择器的钥匙组
- 异常
-
ClosedSelectorException
- 如果此选择器已关闭
-
selectedKeys
public abstract Set<SelectionKey> selectedKeys()
返回此选择器的选择键集。密钥可以从所选密钥集中移除,但不能直接添加。 任何尝试将对象添加到密钥集将导致抛出
UnsupportedOperationException
。所选密钥集是not thread-safe 。
- 结果
- 此选择器的选择键集
- 异常
-
ClosedSelectorException
- 如果此选择器已关闭
-
selectNow
public abstract int selectNow() throws IOException
选择一组其相应通道准备好进行I / O操作的键。此方法执行非阻塞selection operation 。 如果以前的选择操作没有频道变为可选择,则该方法立即返回零。
调用此方法将清除
wakeup
方法之前任何调用的效果。- 结果
- 键的数量,可能为零,其准备操作集由选择操作更新
- 异常
-
IOException
- 如果发生I / O错误 -
ClosedSelectorException
- 如果此选择器已关闭
-
select
public abstract int select(long timeout) throws IOException
选择一组其相应通道准备好进行I / O操作的键。此方法执行阻止selection operation 。 只有在至少选择一个通道之后,才会返回此选择器的
wakeup
方法,当前线程被中断,或给定的超时期限到期,以先到者为准。该方法不提供实时保证:它调用超时,就像调用
Object.wait(long)
方法一样。- 参数
-
timeout
- 如果为正,则阻止最多timeout
毫秒,或多或少,同时等待通道准备就绪; 如果零,无限期地阻止; 不能是负面的 - 结果
- 键的数量,可能为零,其即时操作集更新
- 异常
-
IOException
- 如果发生I / O错误 -
ClosedSelectorException
- 如果此选择器已关闭 -
IllegalArgumentException
- 如果timeout参数的值为负
-
select
public abstract int select() throws IOException
选择一组其相应通道准备好进行I / O操作的键。此方法执行阻止selection operation 。 只有在至少选择一个通道之后,才会返回此选择器的
wakeup
方法,或当前线程中断,以先到者为准。- 结果
- 键的数量,可能为零,其即时操作集更新
- 异常
-
IOException
- 如果发生I / O错误 -
ClosedSelectorException
- 如果此选择器已关闭
-
wakeup
public abstract Selector wakeup()
导致尚未返回的第一个选择操作立即返回。如果另一个线程在调用
select()
或select(long)
方法时被阻止,则该调用将立即返回。 如果当前没有选择操作,则下一次调用这些方法之一将立即返回,除非同时调用了selectNow()
方法。 无论如何,该调用返回的值可能不为零。select()
或select(long)
方法的后续调用将像往常一样阻止,除非此时再次调用此方法。在两次连续的选择操作之间多次调用此方法的效果与调用一次只有一次相同。
- 结果
- 这个选择器
-
close
public abstract void close() throws IOException
关闭此选择器。如果一个线程当前被阻塞在这个选择器的选择方法之一,那么它被中断,好像通过调用选择器的
wakeup
方法。仍然与此选择器相关联的任何未经取消的密钥无效,其通道被注销,并且释放与此选择器相关联的任何其他资源。
如果此选择器已关闭,则调用此方法将不起作用。
选择器关闭后,除了通过调用此方法或
wakeup
方法外,任何进一步尝试使用它将导致抛出ClosedSelectorException
。- Specified by:
-
close
在接口AutoCloseable
- Specified by:
-
close
在接口Closeable
- 异常
-
IOException
- 如果发生I / O错误
-
-