4 Java I/O:AIO和NIO中的Selector

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

4 Java I/O:AIO和NIO中的Selector

文章插图
Selector通过控制单个线程处理多个Channel,如果应用打开了多个Channel,但每次传输的流量都很低,使用Selector就会很方便(至于为什么,具体到Netty中再分析) 。所以使用Selector的好处就显而易见:用最少的资源实现最多的操作,避免了线程切换带来的开销 。
还是以代码为例来演示Selector的作用 。新建一个类,在main()方法中输入下面的代码:
/** * NIO中的Selector * * @author xiangwang */public class TestSelector {public static void main(String args[]) throws IOException {// 创建ServerSocketChannelServerSocketChannel 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();}}}}【4 Java I/O:AIO和NIO中的Selector】代码写好后启动ServerSocketChannel服务,可以看到我这里已经启动成功:
4 Java I/O:AIO和NIO中的Selector

文章插图
然后在网上下载一个叫做SocketTest.jar的工具(在一些工具网站下载的时候当心中毒,如果不放心,可以私信我,给你地址),双击打开,并按下图方式执行:
4 Java I/O:AIO和NIO中的Selector

文章插图
点击「Connect」可以看到变化:
4 Java I/O:AIO和NIO中的Selector

文章插图
然后点击「Disconnect」,再输入「9090」后,再点击「Connect」试试:
4 Java I/O:AIO和NIO中的Selector

文章插图
可以看到结果显示结果变了:
4 Java I/O:AIO和NIO中的Selector

文章插图

经验总结扩展阅读