概述
Selector是NIO中实现I/O多路复用的要害类。Selector实现了通过一个线程打点多个Channel,从而打点多个网络毗连的目标。
Channel代表这一个网络毗连通道,我们可以将Channel注册到Selector中以实现Selector对其的打点。一个Channel可以注册到多个差异的Selector中。
当Channel注册到Selector后会返回一个SelectionKey工具,该SelectionKey工具则代表这这个Channel和它注册的Selector间的干系。而且SelectionKey中维护着两个很重要的属性:interestOps、readyOps
interestOps是我们但愿Selector监听Channel的哪些事件。我们将我们感乐趣的事件配置到该字段,这样在selection操纵时,当发明该Channel有我们所感乐趣的事件产生时,就会将我们感乐趣的事件再配置到readyOps中,这样我们就能得知是哪些事件产生了以做相应处理惩罚。
Selector的中的重要属性
Selector中维护3个出格重要的SelectionKey荟萃,别离是
下面的源码理会会说明上面3个荟萃的用处。
Selector 源码理会
下面我们通过一段对Selector的利用流程讲授来进一步深入其实现道理。
首先先来段Selector最简朴的利用片断
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
int port = 5566;
serverChannel.socket().bind(new InetSocketAddress(port));
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while(true){
int n = selector.select();
if(n > 0) {
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey selectionKey = iter.next();
......
iter.remove();
}
}
}
1、Selector的构建
SocketChannel、ServerSocketChannel和Selector的实例初始化都通过SelectorProvider类实现。
ServerSocketChannel.open();
public static ServerSocketChannel open() throws IOException {
return SelectorProvider.provider().openServerSocketChannel();
}
SocketChannel.open();
public static SocketChannel open() throws IOException {
return SelectorProvider.provider().openSocketChannel();
}
Selector.open();
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
我们来进一步的相识下SelectorProvider.provider()
public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return AccessController.doPrivileged(
new PrivilegedAction<>() {
public SelectorProvider run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
① 假如设置了“java.nio.channels.spi.SelectorProvider”属性,则通过该属性值load对应的SelectorProvider工具,假如构建失败则抛异常。
② 假如provider类已经安装在了对系统类加载措施可见的jar包中,而且该jar包的源码目次META-INF/services包括有一个java.nio.channels.spi.SelectorProvider提供类设置文件,则取文件中第一个类名举办load以构建对应的SelectorProvider工具,假如构建失败则抛异常。
③ 假如上面两种环境都不存在,则返回系统默认的SelectorProvider,即,sun.nio.ch.DefaultSelectorProvider.create();
④ 随后在挪用该要领,软件开发,即SelectorProvider.provider()。则返回第一次挪用的功效。
差异系统对应着差异的sun.nio.ch.DefaultSelectorProvider
