6、Selector

    6、Selector

        (1)、特点

            Selector(选择器)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。即用选择器,借助单一线程,就可对数量庞大的活动I/O通道实施监控和维护。

            ①、Netty的IO线程NioEventLoop聚合了Selector(选择器,也叫多路复用器),可以同时并发处理成百上千个客户端连接。

            ②、当线程从某客户端Socket通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。

            ③、线程通常将非阻塞IO的空闲时间用于在其他通道上执行IO操作,所以单独的线程可以管理多个输入和输出通道。

            ④、由于读写操作都是非阻塞的,这就可以充分提升IO线程的运行效率,避免由于频繁I/O阻塞导致的线程挂起。

            ⑤、一个I/O线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

        (2)、核心方法

            ①、open()方法

                得到一个Selector对象

            ②、selectedKeys()方法

                从内部集合中得到所有的SelectionKey,注册到Selector上发生事件的Channel集合 

            ③、select()方法 / select(long timeout)方法(阻塞方法)

                监控所有注册的通道,当其中有IO操作(事件发生)时,该方法返回,并将对应的SelectionKey加入到被选择的SelectionKey集合中,该方法返回这些Channel的数量。

            ④、wakeup()

                唤醒selector,使一个还未返回的select()方法立即返回。

            ⑤、selectNow()(非阻塞)

                执行一个立即返回的select()操作。

public abstract class Selector implements Closeable {
    /**
     * 得到一个Selector对象
     */
    public static Selector open() throws IOException {return SelectorProvider.provider().openSelector();}
    /**
     * 获取所有的SelectionKey集合,代表注册在该Selector上的所有Channel的SelectionKey
     */
    public abstract Set<SelectionKey> keys();
    /**
     * 被选择的SelectionKey结合,返回此Selector的已选择键集,注册到Selector上发生事件的Channel集合
     */
    public abstract Set<SelectionKey> selectedKeys();
    /**
     * 监控所有注册的Channel,当它们中间有需要处理的IO操作时,该方法返回,并将对应的SelectionKey加入被选择的SelectionKey集合中,该方法返回这些Channel的数量
     */
    public abstract int select() throws IOException;
    /**
     * 可以设置超时时长的Select()操作
     */
    public abstract int select(long timeout) throws IOException;
    /**
     * 使一个还未返回的select()方法立即返回
     */
    public abstract Selector wakeup();
    /**
     * 执行一个立即返回的select()操作,该方法不会阻塞线程
     */
    public abstract int selectNow() throws IOException;
    /**
     * 关闭连接器
     */
    public abstract void close() throws IOException;
}

        (3)、SelectionKey

            ①、概述

                SelectionKey为选择键,表示SelectableChannel和Selector之间的注册关系,每次向选择器注册通道时就会选一个事件(选择键)。选择键包含两个表示为整数值的操作集。操作集的每一位都表示该键的通道所支持的一类可选择操作。

            ②、register(Selector sel, int ops):sel为Selector;ops为SelectionKey

                若注册时不止监听一个事件(选择键),则可以使用“位或”操作符连接。

                例:int ops = SelectionKey.OP_READ|SelectionKey.OP_WRITE;

            ③、源码解析

public abstract class SelectionKey {
    /**
     * 读操作:OP_READ = 1
     */
    public static final int OP_READ = 1 << 0;
    /**
     * 写操作:OP_READ = 4
     */
    public static final int OP_WRITE = 1 << 2;
    /**
     * 连接操作:OP_READ = 8
     */
    public static final int OP_CONNECT = 1 << 3;
    /**
     * 接收操作:OP_READ = 16
     */
    public static final int OP_ACCEPT = 1 << 4;
    /**
     * 得到与之关联的channel
     */
    public abstract SelectableChannel channel();
    /**
     * 得到与之关联的Selector对象
     */
    public abstract Selector selector();
    /**
     * 得到与之关联的共享数据
     */
    public final Object attachment() {return attachment;}
    /**
     * 设置或改变监听事件,并返回SelectionKey对象
     */
    public abstract SelectionKey interestOps();
    /**
     * 获取通道已经准备就绪的操作的集合
     */
    public abstract int readyOps();
    /**
     * 检测Channel中读事件是否就绪
     */
    public final boolean isReadable() {
        return (readyOps() & OP_READ) != 0;
    }
    /**
     * 检测Channel中写事件是否就绪
     */
    public final boolean isWritable() {
        return (readyOps() & OP_WRITE) != 0;
    }
    /**
     * 检测Channel中连接是否就绪
     */
    public final boolean isConnectable() {
        return (readyOps() & OP_CONNECT) != 0;
    }
    /**
     * 检测Channel中接收是否就绪
     */
    public final boolean isAcceptable() { return (readyOps() & OP_ACCEPT) != 0; }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值