Java I/O(4):AIO和NIO中的Selector
您好,我是湘王,这是我的云海天,欢迎您来,欢迎您再来~
在Java NIO的三大核心中,除了Channel和Buffer,剩下的就是Selector了。有的地方叫它选择器,也有叫多路复用器的(比如Netty)。
之前提过,数据总是从Channel读取到Buffer,或者从Buffer写入到Channel,单个线程可以监听多个Channel——Selector就是这个线程背后的实现机制(所以得名Selector)。

Selector通过控制单个线程处理多个Channel,如果应用打开了多个Channel,但每次传输的流量都很低,使用Selector就会很方便(至于为什么,具体到Netty中再分析)。所以使用Selector的好处就显而易见:用最少的资源实现最多的操作,避免了线程切换带来的开销。
还是以代码为例来演示Selector的作用。新建一个类,在main()方法中输入下面的代码:
/**
* NIO中的Selector
*
* @author xiangwang
*/
public class TestSelector {
public static void main(String args[]) throws IOException {
// 创建ServerSocketChannel
ServerSocketChannel channel1 = ServerSocketChannel.open();
channel1.socket().bind(new InetSocketAddress("127.0.0.1", 8080));
channel1.configureBlocking(false);
ServerSocketChannel channel2 = ServerSocketChannel.open();
channel2.socket().bind(new InetSocketAddress("127.0.0.1", 9090));
channel2.configureBlocking(false);
// 创建一个Selector对象
Selector selector = Selector.open();
// 按照字面意思理解,应该是这样的:selector.register(channel, event);
// 但其实是这样的:channel.register(selector, SelectionKey.OP_READ);
// 四种监听事件:
// OP_CONNECT(连接就绪)
// OP_ACCEPT(接收就绪)
// OP_READ(读就绪)
// OP_WRITE(写就绪)
// 注册Channel到Selector,事件一旦被触发,监听随之结束
SelectionKey key1 = channel1.register(selector, SelectionKey.OP_ACCEPT);
SelectionKey key2 = channel2.register(selector, SelectionKey.OP_ACCEPT);
// 模板代码:在编写程序时,大多数时间都是在模板代码中添加相应的业务代码
while(true) {
int readyNum = selector.select();
if (readyNum == 0) {
continue;
}
Set<SelectionKey> selectedKeys = selector.selectedKeys();
// 轮询
for (SelectionKey key : selectedKeys) {
Channel channel = key.channel();
if (key.isConnectable()) {
if (channel == channel1) {
System.out.println("channel1连接就绪");
} else {
System.out.println("channel2连接就绪");
}
} else if (key.isAcceptable()) {
if (channel == channel1) {
System.out.println("channel1接收就绪");
} else {
System.out.println("channel2接收就绪");
}
}
// 触发后删除,这里不删
// it.remove();
}
}
}
}


