Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个Channel,从而管理多个网络连接。
1.1 Selector的使用
Selector的创建:Selector selector=Selector.open();
向Selector注册channel:
channel.configureBlocking(false);
SelectionKey key=channel.register(selector,SelectionKey.OP_READ);
为了将Channel和Selector配合使用,必须将channel注册到Selector中。通过SelectableChannel.register()方法实现注册。与Selector使用时,Channel必须处于非阻塞模式下,这就意味着FileChannel不能与Selector一起使用,因为FileChannel不能切换到非阻塞模式。而套接字通道可以。
register(Selector sel,int ops)方法的第二个参数是指interest集合,意思是通过Selector监听channel时对是什么事件感兴趣。可以监听四种类型的事件:
Connect,Accept,Read,Write。
这四种事件可以用SelectionKey中的四个常量来表示:
SelectionKey.OP_CONNECT,SelectionKey.OP_ACCEPT,SelectionKey.OP_READ,
SelectionKey.OP_WRITE
如果你不止对一种事件感兴趣,你可以使用或操作连接事件:
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
1.2 SelectionKey
SelectionKey代表了一个channel与一个selector之间的注册关系。其中包含了一些重要的信息:
(1)interest集合
(2)ready集合
(3)channel
(4)selector
获得interest集合:selectionKey.interestOps();
boolean isInterestedInAccept=(key.interestOps()&SelectionKey.OP_ACCEPT)==SelectionKey.OP_ACCEPT;
ready集合是通道已经准备就绪的操作的集合。
selectionKey.readyOps();
判断事件是否就绪也可以通过boolean selectionKey.isAcceptable();
SelectionKey获得channel和selector:
Channel channel=selectionKey.channel();
Selector selector=selectionKey.selector();
1.3 Selector
一旦向selector注册了一个或者多个通道,就可以通过select()方法返回你感兴趣的已经准备就绪的事件的个数。如果没有准备就绪的channel,那么这个方法就会阻塞。
当selector.select()拥有返回值时,那么代表已经捕获到了你感兴趣的事件。此时可以通过:
Set<SelectionKey> keys=selector.selectedKeys();
返回所有就绪的通道的键集合。通过键集合中的SelectionKey可以获得channel,从而向channel读或者写数据。
用完Selector后调用其close()方法会关闭该Selector,且使注册到该Selector上的所有SelectionKey实例无效。通道本身并不会关闭。