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

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();
            }
        }
    }
}
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » Java I/O(4):AIO和NIO中的Selector