java NIO

NIO1主要需要理解Selector,SelectableChannel和SelectionKey三个类之间的关系以及用法.

Selector管理注册到Selector上SelectableChannel集合的就绪状态信息。它的核心是选择过程(select方法),他是通过调用底层操作系统select /poll或类系调用来完成的,所以Selector的实现依赖于操作系统;Selector维护着三个集合:1.key set代表SelectableChannel注册到Selector上的对应的SelectionKey的集合(听起来很绕,理解了SelectionKey就明白了);2.selected-key set:Selector检测到ready的SelectableChannel对应的SelectionKey的集合(这里的ready是指SelectableChannel感兴趣的Event发生并可以使用,深入理解这一点需要了解用户空间和内核空间的关系);3.cancelled-key:被SelectableChannel  cancel掉但是还没有撤销register的SelectionKey的集合;

SelectableChannel可选择的Channel,SelectableChannel可以注册到Selector上,指定SelectableChannel感兴趣的操作,当指定的操作发生时Selector会检测到(detect)

SelectionKey选择键,SelectableChannel注册到Selector上,这种注册关系通过SelectionKey表示(A selectable channel's registration with a selector is represented by a link SelectionKey object.)

 

 

The selector waits for incoming connections into an infinite loop (waits for events recorded on the
selector). Usually the Selector.select() method is the first line in the loop, and it blocks the application
until at least one channel is selected, the selector’s Selector.wakeup() method is invoked, or the current
thread is interrupted—whichever comes first. (In addition, a “select() with timeout” method is
available, as is a non-blocking method called selectNow().)

 

 

注意

1.Selector方法selectedKeys()和keys()方法是非线程安全的

2.Selector.select()可能返回0 发生的时机可能是当前Selector管理的SelectableChannel就绪状态没有改变,但是上一次select调用后存在未被处理的SelectableChannel

http://stackoverflow.com/questions/9939989/java-nio-selector-select-returns-0-although-channels-are-ready

3.特别注意NIO与多线程的配合使用,建议处理SelectableChannel部分不要多线程

4.注意与ByteBuffer的配合使用,读取时确保ByteBuffer有空间,写入时确保position和limit之间有数据

 

 

选择器,可选择通道和选择键类

选择器(Selector)
选择器类管理着一个被注册的通道集合的信息和它们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。当这么做的时候,可以选择将被激发的线程挂,直到有就绪的的通道。

维护着三个集合

已注册的键的集合(Registered key set)
与选择器关联的已经注册的键的集合。并不是所有注册过的键都仍然有效。这个集合通过keys( )方法返回,并且可能是空的。这个已注册的键的集合不是可以直接修改的;试图这么做的话将引 java.lang.UnsupportedOperationException。
已选择的键的集合(Selected key set)
已注册的键的集合的子集。这个集合的每个成员都是相关的通道被选择器(在前一个选择操作中)判断为已经准备好的,并且包含于键的 interest 集合中的操作。这个集合通过 selectedKeys( )方法返回(并有可能是空的)。不要将已选择的键的集合与 ready 集合弄混了。这是一个键的集合,每个键都关联一个已经准备好至少一种操作的通道。每个键都有一个内嵌的 ready 集合,指示了所关联的通道已经准备好的操作。

键可以直接从这个集合中移除,但不能添加。试图向已选择的键的集合中添加元素将抛出
java.lang.UnsupportedOperationException。

已取消的键的集合(Cancelled key set)
已注册的键的集合的子集,这个集合包含了 cancel( )方法被调用过的键(这个键已经被无效化),但它们还没有被注销。这个集合是选择器对象的私有成员,因而无法直接访问。在一个刚初始化的 Selector 对象中,这三个集合都是空的。

 

可选择通道(SelectableChannel)

这个抽象类提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。

选择键(SelectionKey)

选择键封装了特定的通道与特定的选择器的注册关系。选择键对象被SelectableChannel.register( ) 返回并提供一个表示这种注册关系的标记。选择键包含了两个比特集(以整数的形式进行编码),指示了该注册关系所关心的通道操作,以及通道已经准备好的操作。一个键表示了一个特定的通道对象和一个特定的选择器对象之间的注册关 系 。

键对象表示了一种特定的注册关系。当应该终结这种关系的时候,可以调用 SelectionKey对象的 cancel( )方法。可以通过调用 isValid( )方法来检查它是否仍然表示一种有效的关系。当键被取消时,它将被放在相关的选择器的已取消的键的集合里。注册不会立即被取消,但键会立即失效(参见 4.3 节)。当再次调用 select( )方法时(或者一个正在进行的 select()调用结束时),已取消的键的集合中的被取消的键将被清理掉,并且相应的注销也将完成。通道会被注销,而新的SelectionKey 将被返回。

当通道关闭时,所有相关的键会自动取消(记住,一个通道可以被注册到多个选择器上)。当选择器关闭时,所有被注册到该选择器的通道都将被注销,并且相关的键将立即被无效化(取消)。一旦键被无效化,调用它的与选择相关的方法就将抛出 CancelledKeyException。

posted on 2014-04-26 10:58  ukouryou  阅读(159)  评论(0编辑  收藏  举报

导航