概述
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