JavaSE:NIO - 选择键(SelectionKey) & Selector的使用流程
1. 选择键
Channel 和 Selector的关系确定好后,并且一旦通道处于某种就绪状态,就可以被选择器查询到。
那么,怎么进行查询呢?
这个工作,使用选择器Selector的select() 方法完成。
select()方法:对感兴趣的通道操作,进行就绪状态的查询。
Selector可以不断地查询Channel中发生的操作的状态。并且挑选感兴趣的操作的就绪状态。
一旦通道有操作的就绪状态达成,并且是Selector感兴趣的操作,就会被Selector选中,放入选择键集合中。
select(): 选择器等待客户端连接的方法
阻塞问题:
1. 在开始没有客户访问的时候,是阻塞的
2. 在有客户来访问的时候,方法会变成非阻塞的
3. 如果客户的访问,被处理结束之后,又会恢复成阻塞的
selectedKeys(): 选择器会把被连接的服务器对象,放在Set集合中,这个方法就是返回一个Set集合
2. Selector的使用流程
<1> 创建Selector
Selector对象,是通过调用静态工厂方法open(),来实例化的,如下:
1 // 1. 获取Selector选择器 2 Selector selector = Selector.open();
<2>将Channel注册到Selector
要实现Selector管理Channel,需要将channel注册到相应的Selector上:
1 // 2. 获取通道 2 3 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 4 5 6 7 // 3. 设置为非阻塞 8 9 serverSocketChannel.configureBlocking(false); 10 11 12 13 // 4. 绑定连接 14 15 serverSocketChannel.bind(new InetSocketAddress(SystemConfig.SOCKET_SERVER_PORT)); 16 17 18 19 // 5. 将通道注册到选择器上, 并制定监听事件为:"接收"事件 20 21 serverSocketChannel.register(selector, Selection.OP_ACCEPT);
上面通过调用通道的register()方法,会将它注册到一个选择器上
首先需要注意的是:
与Selector一起使用时,Channel必须处于非阻塞模式下,否则将抛出异常IllegalBlockingModeException
3. 轮询查询就绪操作
万事俱备,下一步是查询就绪的操作
通过Selector的select()方法,可以查询出已经就绪的通道操作,这些就绪的状态集合,包存在一个元素是SelectionKey对象的Set集合中。
select()方法返回的int值,表示有多少通道已经就绪
而一旦调用select()方法, 并且返回值不为0时,下一步该怎么做?
通过调用Selector的selectedKeys()方法,来访问已选择键集合,然后迭代集合的每一个选择键元素,根据就绪操作的类型,
完成对应的操作(见下篇:NIO编程实例)。