这种模式通常在 Java 中用于实现依赖注入或服务定位 调用SelectorProvider#provider(), 以获得提供者 AccessController : 进入安全管理的特权模式, 以便读写文件 通过属性加载提供者 通过Service实现加载提供者 通过默认实现选择器提供者, 创建提供者 public static SelectorProvider provider() { synchronized return AccessController.doPrivileged( // 进入安全管理的特权模式, 以便读写文件 new PrivilegedAction<SelectorProvider >() { public SelectorProvider run() { if (loadProviderFromProperty
().openSelector(); } 继续往下跟踪就是我们要介绍的关键了SelectorProvider.provider() public static SelectorProvider >() { public SelectorProvider run() { //loadProviderFromProperty方法是通过JDK的参数//-Djava.nio.channels.spi.SelectorProvider } 总结SelectorProvider的创建分三步进行: (1)由JDK的参数-Djava.nio.channels.spi.SelectorProvider=class设置的class来反射构造SelectorProvider class来反射构造SelectorProvider,找不到就跳转到步骤(3) (3)调用不同操作系统版本的JDK里自带的sun.nio.ch.DefaultSelectorProvider来创建SelectorProvider 一般都会走到最后的步骤(3),而这个步骤里创建的SelectorProvider在各个操作系统对应的JDK里各不相同。
SelectorProvider的存在,使得同一套Java代码能够无缝适配epoll、kqueue、IOCP、poll等截然不同的内核多路复用机制。 本文将基于JDK25的最新源码,对SelectorProvider进行原子级的解构。 优先级2:ServiceLoader标准发现展开代码语言:TXTAI代码解释ServiceLoader<SelectorProvider>sl=ServiceLoader.load(SelectorProvider.class 5.3虚拟线程的透明兼容SelectorProvider创建的Selector和SocketChannel天然支持虚拟线程。 Java的SelectorProvider提供了显式的扩展点,适合需要深度定制的场景,但增加了配置复杂度。
public NioEventLoopGroup(int nThreads) { // SelectorProvider提供者 this(nThreads, SelectorProvider.provider ()); } public NioEventLoopGroup(int nThreads, final SelectorProvider selectorProvider) { DEFAULT_EVENT_LOOP_THREADS : nThreads, selectorProvider, DefaultEventExecutorChooserFactory.INSTANCE) provider; public NioEventLoop(SelectorProvider selectorProvider) { this.provider = selectorProvider; this.selector = openSelector(); } private Selector openSelector()
而对应SelectorProvider来说,默认的实现是SelectorProvider.provider(), 我们看下这个方法的具体实现: public static SelectorProvider >() { public SelectorProvider run() { if (loadProviderFromProperty 第一种就是从系统属性中查找:java.nio.channels.spi.SelectorProvider: String cn = System.getProperty("java.nio.channels.spi.SelectorProvider 他实际是从上面提到的默认的SelectorProvider来创建的。 private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); return
selectorProvider) { this(nThreads, threadFactory, selectorProvider, DefaultSelectStrategyFactory.INSTANCE ( int nThreads, Executor executor, final SelectorProvider selectorProvider) { this (int nThreads, Executor executor, final SelectorProvider selectorProvider, static SelectorProvider provider() { synchronized (lock) { if (provider ! selectorProvider) 在此构造函数中提供了DefaultSelectStrategyFactory.INSTANCE来创建默认选择策略工厂。
而对应SelectorProvider来说,默认的实现是SelectorProvider.provider(), 我们看下这个方法的具体实现: public static SelectorProvider >() { public SelectorProvider run() { if (loadProviderFromProperty 第一种就是从系统属性中查找:java.nio.channels.spi.SelectorProvider: String cn = System.getProperty("java.nio.channels.spi.SelectorProvider 他实际是从上面提到的默认的SelectorProvider来创建的。 private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); return
().openSelector(); } 我们来进一步的了解下SelectorProvider.provider() public static SelectorProvider provider ”属性,则通过该属性值load对应的SelectorProvider对象,如果构建失败则抛异常。 提供类配置文件,则取文件中第一个类名进行load以构建对应的SelectorProvider对象,如果构建失败则抛异常。 ③ 如果上面两种情况都不存在,则返回系统默认的SelectorProvider,即,sun.nio.ch.DefaultSelectorProvider.create(); ④ 随后在调用该方法,即SelectorProvider.provider . */ public static SelectorProvider create() { return new sun.nio.ch.EPollSelectorProvider
SelectorProvider就是用来创建Selector的。 threadFactory) { this(0, threadFactory, SelectorProvider.provider()); }SelectorProvider是在前面介绍的 SelectorProvider的加载过程:public abstract class SelectorProvider { public static SelectorProvider provider 加载源码中我们可以看出,SelectorProvider的加载方式有三种,优先级如下:通过系统变量-D java.nio.channels.spi.SelectorProvider指定SelectorProvider 用于判断由SelectorProvider创建出来的Selector是否为JDK默认实现(SelectorProvider第三种加载方式)。
().openSelector(); } 我们来进一步的了解下SelectorProvider.provider() public static SelectorProvider provider ”属性,则通过该属性值load对应的SelectorProvider对象,如果构建失败则抛异常。 提供类配置文件,则取文件中第一个类名进行load以构建对应的SelectorProvider对象,如果构建失败则抛异常。 ③ 如果上面两种情况都不存在,则返回系统默认的SelectorProvider,即,sun.nio.ch.DefaultSelectorProvider.create(); ④ 随后在调用该方法,即SelectorProvider.provider . */ public static SelectorProvider create() { return new sun.nio.ch.EPollSelectorProvider
SelectorProvider.provider()返回一个默认的SelectorProvider,用于创建Selector实例。 selectorProvider表示一个SelectorProvider,用于创建Selector实例。 继续 public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider selectorProvider表示一个SelectorProvider,用于创建Selector实例。 、SelectStrategyFactory和RejectedExecutionHandler SelectorProvider selectorProvider = (SelectorProvider
} which is returned by {@link SelectorProvider#provider()}. */ public NioEventLoopGroup(int nThreads 然后到: public NioEventLoopGroup( int nThreads, Executor executor, final SelectorProvider selectorProvider ) { this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE); } public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) { super(nThreads, executor, selectorProvider
selectorProvider) { this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE == null) { throw new NullPointerException("selectorProvider"); } if (strategy == null ) { throw new NullPointerException("selectStrategy"); } provider = selectorProvider; NioEventLoop 属性: SelectorProvider provider 属性: NioEventLoopGroup 构造器中通过 SelectorProvider.provider() 获取一个 SelectorProvider Selector selector 属性: NioEventLoop 构造器中通过调用通过 selector = provider.openSelector(
} //调用下面 public NioEventLoopGroup( int nThreads, ThreadFactory threadFactory, final SelectorProvider selectorProvider) { this(nThreads, threadFactory, selectorProvider, DefaultSelectStrategyFactory.INSTANCE ///调用下面 public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) { super(nThreads, threadFactory SelectorProvider.provider()这个方法前面介绍过,会根据当前系统来选择核实的io多路复用(select、poll、epoll)。
ServerBootstrap(); serverBootstrap.group( bossGroup, workerGroup); 源码解析 跨平台实现的根本 public static SelectorProvider return provider; return AccessController.doPrivileged( new PrivilegedAction<SelectorProvider >() { public SelectorProvider run() { if (loadProviderFromProperty
().openServerSocketChannel(); } 在这个方法中进行了两步操作,第一步调用SelectorProvider的provider方法 public static SelectorProvider ( new PrivilegedAction<SelectorProvider>() { public SelectorProvider run( 实例 loadProviderFromProperty()这个函数判断如果系统属性java.nio.channels.spi.SelectorProvider 已经被定义了,则该属性名看作具体提供者类的完全限定名 其构造器如下: ServerSocketChannelImpl(SelectorProvider var1) throws IOException { super(sp); this.fd (这里不同的系统会有不同的SelectorProvider实现类)的openSelector()方法来创建新的selector SelectorProvider.provider()这个方法我们已经在上文分析过
DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider(); 那么上面提到channel的创建是基于反射构造函数创建的,我们看看代码,这里调用了一个 newSocket()方法,还将SelectorProvider传进去。 io.netty.channel.socket.nio.NioServerSocketChannelprivate static ServerSocketChannel newSocket(SelectorProvider provider) { try { /** * Use the {@link SelectorProvider} to open {@link SocketChannel } and so remove condition in * {@link SelectorProvider#provider()} which is called
()); } public NioEventLoopGroup( int nThreads, Executor executor, final SelectorProvider selectorProvider) { this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE ); } public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider selectorProvider, SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler , "selectorProvider"); this.selectStrategy = ObjectUtil.checkNotNull(strategy, "selectStrategy");
主要用它获取selector选择器 this(nThreads, executor, SelectorProvider.provider()); } 这里面多传递了一个 SelectorProvider.provider selectorProvider) { this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) { super(nThreads, executor, selectorProvider, 我们上一步传递过来的selectorProvider、拒绝策略、selectStrategyFactory被封装为数组,并放在args[0],args[1], args[2]的位置!
hashCode()); serverSocketChannel1.close(); serverSocketChannel2.close(); } } 6.获取selectorProvider /** * 获取selectorProvider */ public class SelectorProviderTest { public static void main(String [] args) throws IOException { SelectorProvider selectorProvider = SelectorProvider.provider() ; System.out.println(selectorProvider); ServerSocketChannel serverSocketChannel = null ; serverSocketChannel =serverSocketChannel.open(); SelectorProvider provider = SelectorProvider.provider