星球狂想战队|深度解读Netty:NIO那些不为人知的秘密( 五 )


概念
Selector是NIO中最为重要的组件之一 , 我们常常说的多路复用器就是指的Selector组件 。 Selector组件用于轮询一个或多个NIOChannel的状态是否处于可读、可写 。 通过轮询的机制就可以管理多个Channel , 也就是说可以管理多个网络连接 。
首先 , 需要将Channel注册到Selector上 , 这样Selector才知道需要管理哪些Channel接着Selector会不断轮询其上注册的Channel , 如果某个Channel发生了读或写的时间 , 这个Channel就会被Selector轮询出来 , 然后通过SelectionKey可以获取就绪的Channel集合 , 进行后续的IO操作 。
创建Selector通过open()方法 , 我们可以创建一个Selector对象 。
Selectorselector=Selector.open();注册Channel到Selector中我们需要将Channel注册到Selector中 , 才能够被Selector管理 。
channel.configureBlocking(false);SelectionKeykey=channel.register(selector,SelectionKey.OP_READ);某个Channel要注册到Selector中 , 那么该Channel必须是非阻塞 , 所有上面代码中有个configureBlocking()的配置操作 。
在register(Selectorselector,intinterestSet)方法的第二个参数 , 标识一个interest集合 , 意思是Selector对哪些事件感兴趣 , 可以监听四种不同类型的事件:
publicstaticfinalintOP_READ=1<<0;publicstaticfinalintOP_WRITE=1<<;publicstaticfinalintOP_CONNECT=1<<3;publicstaticfinalintOP_ACCEPT=1<<4;Connect事件:连接完成事件(TCP连接) , 仅适用于客户端 , 对应SelectionKey.OP_CONNECT 。 Accept事件:接受新连接事件 , 仅适用于服务端 , 对应SelectionKey.OP_ACCEPT 。 Read事件:读事件 , 适用于两端 , 对应SelectionKey.OP_READ , 表示Buffer可读 。 Write事件:写时间 , 适用于两端 , 对应SelectionKey.OP_WRITE , 表示Buffer可写 。Channel触发了一个事件 , 表明该事件已经准备就绪:
一个ClientChannel成功连接到另一个服务器 , 成为“连接就绪”一个ServerSocket准备好接收新进入的接 , 称为“接收就绪”一个有数据可读的Channel , 称为“读就绪”一个等待写数据的Channel , 称为”写就绪“当然 , Selector是可以同时对多个事件感兴趣的 , 我们使用或运算即可组合多个事件:
intinterestSet=SelectionKey.OP_READ|SelectionKey.OP_WRITE;Selector其他一些操作
选择Channel
publicabstractintselect()throwsIOException;publicabstractintselect(longtimeout)throwsIOException;publicabstractintselectNow()throwsIOException;当Selector执行select()方法就会产生阻塞 , 等到注册在其上的Channel准备就绪就会立即返回 , 返回准备就绪的数量 。
select(longtimeout)则是在select()的基础上增加了超时机制 。 selectNow()立即返回 , 不产生阻塞 。
有一点非常需要注意:select方法返回的int值 , 表示有多少Channel已经就绪 。
自上次调用select方法后有多少Channel变成就绪状态 。 如果调用select方法 , 因为有一个Channel变成就绪状态则返回了1;
若再次调用select方法 , 如果另一个Channel就绪了 , 它会再次返回1 。


推荐阅读