传统的IO 编程中,针对每一个客户端连接都会创建一个新的线程;
而 NIO 一个线程可以处理很多客户端的请求
我们分析源码的注解,可以归纳出:
1. Selector 构造方式:(常见的Seletor 构造方式)
源码:
* <p> A selector may be created by invoking the {@link #open open} method of
* this class, which will use the system's default {@link
* java.nio.channels.spi.SelectorProvider selector provider} to
* create a new selector. A selector may also be created by invoking the
* {@link java.nio.channels.spi.SelectorProvider#openSelector openSelector}
* method of a custom selector provider. A selector remains open until it is
* closed via its {@link #close close} method.
翻译:
Selector 是通过调用这个类的open()方法进行创建的,它使用的是系统默认的 选择器提供者去创建一个新的Selector;
也可以调用spi 里的 openSelector 方法进行自定义Selector 的创建;
在调用close 方法之前,Selector 是保持打开的;
结果:
Selector selector = Selector.open(); //Selector 构造方式
2. 关于通道的注册以及selector 管理通道发生的事件(selector 是通过事件进行监听的)
源码:
* <p> A key is added to a selector's key set as a side effect of registering a * channel via the channel's {@link SelectableChannel#register(Selector,int) * register} method. Cancelled keys are removed from the key set during * selection operations. The key set itself is not directly modifiable.
翻译解析:
我们可以通提供过继承了 SelectableChannel 的类的 register 方法进行通道的注册,返回SelectionKey 在注册的同时,一个key 也会加入到选择器的键集里;
需要注意的是 只有继承了 SelectableChannel 的类 才能够进行注册;
在注册方法中有两个参数 SelectionKey register(Selector sel, int ops) ;Selector 就是我们的选择器, ops 是我们需要监听的事件,
以socketChannel 为例:
//创建Selector 选择器对象
Selector selector = Selector.open();
//创建ServerSocketChannel
ServerSocketChannel socketChannel = ServerSocketChannel.open();
//设置非阻塞模式
socketChannel.configureBlocking(false);
//创建ServerSocket 绑定端口
ServerSocket socket=socketChannel.socket();
socket.bind(new InetSocketAddress(9999));
//进行通道的注册
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
3.. SelectionKey : SelectionKey 是 java NIO 中重要的值(我们可以认为是通道注册的唯一值):
源码:
* <p> A selectable channel's registration with a selector is represented by a * {@link SelectionKey} object. A selector maintains three sets of selection * keys:
翻译:
selector 选择器中可选择的通道注册是由 SelectionKey 这个对象表示的,也就是说,在Selector 注册的不同通道,都会有一个 SelectionKey 对应;,这个
SelectionKey 是可以追溯的,也可以通过 SelectionKey 来获取当前 SelectionKey 的通道channel;
一个选择器里维护了三种选择集 分别是如下:
源码:
* <li><p> The <i>key set</i> contains the keys representing the current
* channel registrations of this selector. This set is returned by the
* {@link #keys() keys} method. </p></li>
*
* <li><p> The <i>selected-key set</i> is the set of keys such that each
* key's channel was detected to be ready for at least one of the operations
* identified in the key's interest set during a prior selection operation.
* This set is returned by the {@link #selectedKeys() selectedKeys} method.
* The selected-key set is always a subset of the key set. </p></li>
*
* <li><p> The <i>cancelled-key</i> set is the set of keys that have been
* cancelled but whose channels have not yet been deregistered. This set is
* not directly accessible. The cancelled-key set is always a subset of the
* key set. </p></li>
翻译理解:
1. 键集:包含了选择器里当前通道注册的键,可以通过keys 方法进行返回这个键集;它是最全所有的键集
2.selected 键集 : 一句话就是当前selector 监听的事件(感兴趣的事件)触发返回的一个键集合, 可以通过selectKeys()方法进行获取;它是键集(1)的子类
3. cancelled 键集:是一个被取消的键集,但是通道还没有被撤销登记,这几集合不能直接被操作,也是键集(1)的子类