Module java.base

Class Selector

java.lang.Object
java.nio.channels.Selector
所有已实现的接口:
Closeable, AutoCloseable
直接已知的子类:
AbstractSelector

public abstract class Selector extends Object implements Closeable
一个SelectableChannel对象的复用器。

可以通过调用此类的open方法来创建选择器,该方法将使用系统的默认选择器提供程序来创建一个新的选择器。也可以通过调用自定义选择器提供程序的openSelector方法来创建选择器。选择器保持打开状态,直到通过其close方法关闭为止。

可选择通道与选择器的注册由SelectionKey对象表示。选择器维护三组选择键:

  • 键集包含表示此选择器当前通道注册的键。此集合由keys方法返回。

  • 已选择键集是这样一组键,使得每个键的通道在先前的选择操作中被检测到至少准备执行键兴趣集中标识的操作之一。此集合由selectedKeys方法返回。已选择键集始终是键集的子集。

  • 已取消键集是已取消但其通道尚未注销的键集。此集合无法直接访问。已取消键集始终是键集的子集。

register方法注册通道的副作用。取消的键在选择操作期间从键集中移除。键集本身无法直接修改。

cancel方法。取消键将导致其通道在下一次选择操作期间被注销,此时该键将从选择器的所有键集中移除。

remove方法或通过调用从集合获取的 remove方法来直接从已选择键集中移除键。通过调用集合的 clear方法可以从已选择键集中移除所有键。无法直接向已选择键集中添加键。

选择

  1. select()select(long)selectNow()方法将准备执行操作的通道的键添加到已选择键集,或更新已选择键集中已存在的准备操作键的集合。

  2. select(Consumer)select(Consumer, long)selectNow(Consumer)方法对每个准备执行操作的通道的键执行一个操作。这些方法不会添加到已选择键集。

添加到已选择键集的选择操作

select()select(long)selectNow()方法执行,并涉及三个步骤:

    如果在此步骤开始时键集中的所有键的兴趣集为空,则已选择键集或任何键的准备操作集都不会被更新。

对已选择键执行操作的选择操作

select(Consumer)select(Consumer,long)selectNow(Consumer)方法执行,并涉及三个步骤:

  1. select方法的 操作来消耗通道的键。在调用 操作之前,将丢弃之前记录在准备集中的任何准备信息。

    操作,通道的键和准备操作集被修改为通道准备执行的操作的子集。如果对同一键多次调用 操作,则其准备操作集永远不会包含在同一选择操作中对 操作的先前调用中包含的操作位。

并发

  • wakeup方法,

  • close方法,或

  • interrupt方法,此时其中断状态将被设置,并且选择器的 wakeup方法将被调用。

close方法按照选择操作中的相同顺序在选择器和其已选择键集上同步。

ConcurrentModificationException

iterator方法返回的迭代器是 快速失败的:如果在创建迭代器后以任何方式修改集合,除了通过调用迭代器自己的 remove方法之外,则将抛出 ConcurrentModificationException

自从:
1.4
参见:
  • Constructor Details

    • Selector

      protected Selector()
      初始化此类的新实例。
  • Method Details

    • open

      public static Selector open() throws IOException
      打开一个选择器。

      通过调用系统范围默认的openSelector方法创建新的选择器。

      返回:
      一个新的选择器
      抛出:
      IOException - 如果发生I/O错误
    • 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
      选择一组键,其对应的通道已准备好进行I/O操作。

      此方法执行非阻塞的选择操作。如果自上次选择操作以来没有通道变为可选择,则此方法立即返回零。

      调用此方法会清除任何先前调用wakeup方法的效果。

      返回:
      键的数量,可能为零,其准备操作集现在指示通道准备好进行至少一类操作,而该通道先前未被检测到准备好进行该类操作
      抛出:
      IOException - 如果发生I/O错误
      ClosedSelectorException - 如果此选择器已关闭
    • select

      public abstract int select(long timeout) throws IOException
      选择一组键,其对应的通道已准备好进行I/O操作。

      此方法执行阻塞的选择操作。仅在至少选择一个通道后返回,此选择器的wakeup方法被调用,当前线程被中断,或给定的超时时间到期时才返回。

      此方法不提供实时保证:它将超时安排为如同调用Object.wait(long)方法一样。

      参数:
      timeout - 如果为正数,则阻塞最多timeout毫秒,等待通道准备就绪;如果为零,则无限期阻塞;不能为负数
      返回:
      键的数量,可能为零,其准备操作集现在指示通道准备好进行至少一类操作,而该通道先前未被检测到准备好进行该类操作
      抛出:
      IOException - 如果发生I/O错误
      ClosedSelectorException - 如果此选择器已关闭
      IllegalArgumentException - 如果超时参数的值为负数
    • select

      public abstract int select() throws IOException
      选择一组键,其对应的通道已准备好进行I/O操作。

      此方法执行阻塞的选择操作。仅在至少选择一个通道后返回,此选择器的wakeup方法被调用,或当前线程被中断时才返回。

      返回:
      键的数量,可能为零,其准备操作集现在指示通道准备好进行至少一类操作,而该通道先前未被检测到准备好进行该类操作
      抛出:
      IOException - 如果发生I/O错误
      ClosedSelectorException - 如果此选择器已关闭
    • select

      public int select(Consumer<SelectionKey> action, long timeout) throws IOException
      选择并对准备好进行I/O操作的键执行操作。

      此方法执行阻塞的选择操作。仅在至少选择一个通道后返回,此选择器的wakeup方法被调用,当前线程被中断,或给定的超时时间到期时才返回。

      指定的actionaccept方法将为每个准备执行其键的操作的键调用。 accept方法可能会多次为同一键调用,但其准备操作集包含通道准备好执行的操作的子集(如上所述)。在选择器及其已选择键集上同步时,应特别小心避免与其他同步在这些对象上的线程发生死锁。通常情况下,选择操作不可重入,因此action应特别小心,不要尝试在同一选择器上执行选择操作。尝试进行可重入选择操作时的行为是特定于实现的,因此未指定。如果action关闭选择器,则在操作完成时会抛出ClosedSelectorException。不禁止action关闭向选择器注册的通道,也不禁止取消键或更改键的兴趣集。如果选择了一个通道,但在执行action之前取消了其键或更改了其兴趣集,则根据实现的具体情况,无法确定是否调用action(可能会使用一个无效键调用)。由操作引发的异常将传递给调用者。

      此方法不提供实时保证:它将超时安排为如同调用Object.wait(long)方法一样。

      实现要求:
      默认实现会从已选择键集中移除所有键,使用给定的超时调用select(long),然后为添加到已选择键集的每个键执行操作。默认实现不会检测执行可重入选择操作的操作。默认实现在完成时可能为空或不为空已选择键集。
      参数:
      action - 要执行的操作
      timeout - 如果为正数,则阻塞最多timeout毫秒,等待通道准备就绪;如果为零,则无限期阻塞;不能为负数
      返回:
      消耗的唯一键的数量,可能为零
      抛出:
      IOException - 如果发生I/O错误
      ClosedSelectorException - 如果此选择器已关闭或由操作关闭
      IllegalArgumentException - 如果超时参数的值为负数
      自从:
      11
    • select

      public int select(Consumer<SelectionKey> action) throws IOException
      选择并对其对应通道已准备好进行I/O操作的键执行操作。

      此方法执行阻塞的选择操作。仅当至少选择了一个通道时,此选择器的wakeup方法被调用,或当前线程被中断时,它才会从查询操作系统中唤醒。

      此方法等效于使用超时时间为0调用具有两个参数的select方法,以无限期阻塞。

      实现要求:
      默认实现使用超时时间为0调用具有两个参数的select方法。
      参数:
      action - 要执行的操作
      返回:
      消耗的唯一键的数量,可能为零
      抛出:
      IOException - 如果发生I/O错误
      ClosedSelectorException - 如果此选择器已关闭或由操作关闭
      自:
      11
    • selectNow

      public int selectNow(Consumer<SelectionKey> action) throws IOException
      选择并对其对应通道已准备好进行I/O操作的键执行操作。

      此方法执行非阻塞的选择操作

      调用此方法会清除任何先前调用wakeup方法的效果。

      实现要求:
      默认实现会从所选键集中移除所有键,调用selectNow(),然后对添加到所选键集中的每个键执行操作。默认实现不会检测执行具有可重入选择操作的操作。默认实现在完成后所选键集可能为空或非空。
      参数:
      action - 要执行的操作
      返回:
      消耗的唯一键的数量,可能为零
      抛出:
      IOException - 如果发生I/O错误
      ClosedSelectorException - 如果此选择器已关闭或由操作关闭
      自:
      11
    • wakeup

      public abstract Selector wakeup()
      使尚未返回的第一个选择操作立即返回。

      如果另一个线程当前被阻塞在选择操作中,则该调用将立即返回。如果当前没有选择操作正在进行,则下一次选择操作的调用将立即返回,除非在此期间调用了selectNow()selectNow(Consumer)。在任何情况下,该调用返回的值可能为非零。后续选择操作将像往常一样阻塞,除非在此期间再次调用此方法。

      在两个连续选择操作之间多次调用此方法具有与仅调用一次相同的效果。

      返回:
      此选择器
    • close

      public abstract void close() throws IOException
      关闭此选择器。

      如果某个线程当前被阻塞在此选择器的选择方法之一中,则会被中断,就像调用选择器的wakeup方法一样。

      仍与此选择器关联的任何未取消键都将无效,它们的通道将被注销,并且与此选择器关联的任何其他资源都将被释放。

      如果此选择器已关闭,则调用此方法不会产生任何效果。

      关闭选择器后,除了调用此方法或wakeup方法之外,任何进一步尝试使用它都将导致抛出ClosedSelectorException

      指定者:
      close 在接口 AutoCloseable
      指定者:
      close 在接口 Closeable
      抛出:
      IOException - 如果发生I/O错误