Java NIO组件介绍
Selector
Selector 能够检测一个或多个Channel是否已经准备好读或写等事件。这样,一个线程就可以管理多个Channel(要知道对于操作系统来讲,频繁切换线程代价是十分昂贵的)。下面是一个Selector处理3个Channel的示意图:
1 创建Selector
Selector selector = Selector.open();
复制代码
2 将channel注册到Selector上
//channel必须设置为非阻塞模式才能够搭配Selector使用
channel.configureBlocking(false);
//第二个参数为感兴趣的事件集合
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
复制代码
事件集合有四种,可以通过或操作注册多个感兴趣事件:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- SelectionKey.OP_WRITE
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
复制代码
3 注册完返回参数SelectionKey
首先介绍SelectionKey包括的属性:
- The interest set:感兴趣的事件集合
- The ready set:哪些事件已经准备好了
- The Channel:注册时的Channel
- The Selector:注册时的Selector
- An attached object (optional):附加对象
4 通过Selector选择Channel
如果注册了多个Channel到Selector可以通过select()来得到已经准备好的Channels(即一个或多个Channel中已经有感兴趣事件触发了)。
- int select():一直阻塞一直有Channel准备好
- int select(long timeout):在指定时间内阻塞一直到Channel准备好
- int selectNow():不阻塞,马上返回,不管Channel有没有准备好
其中返回值int代表有多少个Channel准备好
知道有Channel准备好后,可以通过 selectedKeys()方法获取准备好的Channel:
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if(key.isAcceptable()) {
// a connection was accepted by a ServerSocketChannel.
} else if (key.isConnectable()) {
// a connection was established with a remote server.
} else if (key.isReadable()) {
// a channel is ready for reading
} else if (key.isWritable()) {
// a channel is ready for writing
}
//必须在处理完通道时自己移除SelectionKey,否则下次该通道变成就绪时,Selector会再次将其放入已选择键集中。
keyIterator.remove();
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END