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(); } } } }