Selector简介
Selector(选择器)是javaNIO中能检测一到多个NIO通道,并能够知道通道是否为诸如读写事件做好准备的组件。这样的好处是,一个单独的线程可以管理多个channel,从而可以管理多个网络连接。
1.使用Selector的好处
对于操作系统而言,线程之间上下文切换的开销很大,而且每个线程都要占用系统的一些资源。所以用单个线程来处理多个channels能提高性能。
但是现代操作系统和cpu在多任务方便表现的越来越好,所以多线程的开销随着时间的推移,变得越来越小了。所以可以使用多个Selector.
1.1Selector的创建
通过调用Selector.open()方法创建一个Selector
Selector selector = Selector.open();
1.2向Selector注册通道
为了将Channel和Selector配合使用,必须将channel注册到selector上,通过SelectableChannel.register()方法来实现。
channel.configureBlocking(false);
SelectionKey key = channel.register(selector,
Selectionkey.OP_READ);
register()方法的第二个参数,这是一个“interest集合”,意思是在通过Selector监听Channel时对什么事情感兴趣,有一下4中事件。
Connect
Accept
Read
Write
通道触发了一个事件就是该事件已经就绪。
SelectionKey.OP_CONNECT:某个channel成功连接到另一个服务器称为“连接就绪”
SelectionKey.OP_ACCPET:一个server socket channel准备好接收新进入的连接称为“接收就绪”
SelectionKey.OP_READ:一个有数据可读的通道可以说是读就绪。
SelectionKey.OP_WRITE.等待写数据的通道可以说是写就绪。
1.3SelectionKey
当向Selector注册Channel时,register()方法会返回一个SelectionKey对象,这个对象包含了一些你感兴趣的属性。
interest集合:你所感兴趣的事件集合
ready集合:通道已经准备就绪的集合
Channel:可以访问channel Channel channel = selectionKey.channel();
Selector:可以访问selector Selector selector = selectionKey.selector();
1.4Selector选择通道
一旦向Selector注册一个或者多个通道,可以调用几个重载的select()方法,这些方法返回你所感兴趣的事件(连接,接受,读或写)已经准备就绪的哪些通道。
select():阻塞到至少有一个通道在你注册上的事件就绪了。
select(long timeout):除了最长阻塞timeout毫秒
selectNow()不会阻塞:不管什么通道就绪都立刻返回。
1.5selectKeys()
一旦调用了select方法,并且返回值表明有一个或更多个通道就绪了,然后可以通过调用selector的selectedKeys()方法,访问已选择(selected key set)中的就绪通道。
Set selectedKeys = selector.selectedKeys();
可以遍历这个已选择的键集合来访问就绪的通道。如下:
Set selectedKeys = selector.selectedKeys();
Iterator 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
}
keyIterator.remove();
}
这个循环遍历选择键集中的每个键,并检测各个键所对应的通道的就绪事件。
网友评论