在java中如过需要用到Selector来处理Nio的情况下,需要先使用SelectorProvider的provider()方法来取得相应的SelectorProvider。

public static SelectorProvider provider() {synchronized (lock) {if (provider != null)return provider;return AccessController.doPrivileged(new PrivilegedAction<SelectorProvider>() {public SelectorProvider run() {if (loadProviderFromProperty())return provider;if (loadProviderAsService())return provider;provider = sun.nio.ch.DefaultSelectorProvider.create();return provider;}});}
}

首先,会从系统属性当中去尝试取得相应的SelectorProvider,如果没有取得,如果在规定路径下写了相应的配置文件,则会通过ServiceLoader去尝试加载用户定义的实现类,如果也没有配置,则会采用默认的DefaultSelectorProvider的creat()方法来获取默认的SelectorProvider。

public static SelectorProvider create() {return new WindowsSelectorProvider();
}

这里直接返回了的是WindowsSelectorProvider,也就是说如果没有进行任何的配置,则会采用的是WindowsSelectorProvider,其构造方法就是空的,并没有任何实现。在获得了相应的SelectorProvider之后,调用openSelector()获得相应的Selector。以默认情况为例子。

public AbstractSelector openSelector() throws IOException {return new WindowsSelectorImpl(this);
}

这里也就说明,默认情况下,采用的就是这个WindowsSelectorImpl。

private final Pipe wakeupPipe = Pipe.open();WindowsSelectorImpl(SelectorProvider var1) throws IOException {super(var1);this.wakeupSourceFd = ((SelChImpl)this.wakeupPipe.source()).getFDVal();SinkChannelImpl var2 = (SinkChannelImpl)this.wakeupPipe.sink();var2.sc.socket().setTcpNoDelay(true);this.wakeupSinkFd = var2.getFDVal();this.pollWrapper.addWakeupSocket(this.wakeupSourceFd, 0);
}

从构造方法可以看出,首先会需要用到wakeupPipe,而这个成员的取得需要Pipe调用open()方法。

public static Pipe open() throws IOException {return SelectorProvider.provider().openPipe();
}

直接调用了SelectorProvider的openPipe()方法。

public Pipe openPipe() throws IOException {return new PipeImpl(this);
}

openPipe()方法实现在了WindowsSelectorProvider的父类SelectorProviderImpl类中。

openPipe()的实现调用了pipeImpl的构造方法。

static {Util.load();byte[] var0 = new byte[8];boolean var1 = IOUtil.randomBytes(var0);if(var1) {rnd = new Random(ByteBuffer.wrap(var0).getLong());} else {rnd = new Random();}}PipeImpl(SelectorProvider var1) throws IOException {try {AccessController.doPrivileged(new PipeImpl.Initializer(var1));} catch (PrivilegedActionException var3) {throw (IOException)var3.getCause();}
}

首先,在PipeImpl的静态块中会产生一个随机数保存。

然后在其构造方法中,只是通过AcessController调用了doPrivileged()方法会new一个PipeImpl中内部类Initializer。这个方法会调用传入的类所实现的run()方法,并保证其内部所涉及的权限问题。那么,可以看到其run()方法。

public Void run() throws IOException {ServerSocketChannel var1 = null;SocketChannel var2 = null;SocketChannel var3 = null;try {InetAddress var4 = InetAddress.getByName("127.0.0.1");assert var4.isLoopbackAddress();var1 = ServerSocketChannel.open();var1.socket().bind(new InetSocketAddress(var4, 0));InetSocketAddress var20 = new InetSocketAddress(var4, var1.socket().getLocalPort());var2 = SocketChannel.open(var20);ByteBuffer var6 = ByteBuffer.allocate(8);long var7 = PipeImpl.rnd.nextLong();var6.putLong(var7).flip();var2.write(var6);while(true) {var3 = var1.accept();var6.clear();var3.read(var6);var6.rewind();if(var6.getLong() == var7) {PipeImpl.this.source = new SourceChannelImpl(this.sp, var2);PipeImpl.this.sink = new SinkChannelImpl(this.sp, var3);return null;}var3.close();}} catch (IOException var18) {try {if(var2 != null) {var2.close();}if(var3 != null) {var3.close();}} catch (IOException var17) {;}IOException var5 = new IOException("Unable to establish loopback connection");var5.initCause(var18);throw var5;} finally {try {if(var1 != null) {var1.close();}} catch (IOException var16) {;}}
}

在其run()方法中,首先会尝试去构造两条SocketChannel来来联通成一条ServerSocketChannel。首先,会调用ServerSocketChannel的open()方法,其中会通过刚刚的SelectorProvider的openServerSocketChannel()来打开一个,其方法的具体实现写在了SelectorProviderImpl中,直接返回了一个ServerSocketChannelImpl的构造方法。

ServerSocketChannelImpl(SelectorProvider var1) throws IOException {super(var1);this.fd = Net.serverSocket(true);this.fdVal = IOUtil.fdVal(this.fd);this.state = 0;
}

在其构造方法中,会新建一个socket并且得到他的fd和fdVal。

之后该ServerSocketChannelImpl新生成的socket会绑定本机的0号端口。之后会根据这个socket的ip和端口去生成一个新的SocketChannel,在两者都创建完毕之后,会将一开始PipeImpl的静态块中生成的随机数从第二个SocketChannel发送到第一个,之后会在不断地循环中去等待第一个接收到信息并与发送的随机数验证,如果无误,说明一条Pipe被成功建立起来。

在成功建立起来之后,回到WindowsSelectorImpl的构造方法,将会保存PipeImpl的sink端的socket的fdVal,而将会把source端的fdVal保存在pollWrpper中。

Selector的创建完毕。

jdk的selector(1)相关推荐

  1. jdk的Selector(3)select的过程

    当调用了SelectorImpl的select()方法的时候,同时会将所带的参数,也就是给select()所设置的timeout,之后会调用lockAndDoSelect(),在这个方法中,主要还是调 ...

  2. jdk的selector(2)channel的注册

    Selector中的channel注册需要由SelectabelChannel调用其register()方法开始注册流程.具体的register()方法实现在了AbstractSelectableCh ...

  3. Java NIO类库Selector机制解析--转

    一.  前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但引入了全新的高效的I/O机制,同时,也引入了多路复用的异步模式.NIO的包中主要包含了这样几种抽象数据类型: ...

  4. 高并发核心Selector详解

    Selector设计 笔者下载得是openjdk8的源码, 画出类图 比较清晰得看到,openjdk中Selector的实现是SelectorImpl,然后SelectorImpl又将职责委托给了具体 ...

  5. netty源码分析系列——EventLoop

    2019独角兽企业重金招聘Python工程师标准>>> 前言 EventLoop也是netty作为一个事件驱动架构的网络框架的重要组成部分,netty主要通过它来实现异步编程,从前面 ...

  6. 深入剖析通信层和RPC调用的异步化(上)

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析通信层和 RPC 调用的异步化.李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的 ...

  7. NIO详解(四):NIO编程

    1. NIO类库简介 1.1 缓冲区Buffer Buffer是一个对象,它包含了一些要写入或者要读出的数据.在NIO类库中加入Buffer对象,体现了新库和原来I/O的一个重要区别.在NIO库中,所 ...

  8. Netty详解(二)Linux 网络IO模型

    1. Linux I/O基础知识 针对linux操作系统而言,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为内核空间,而将较低的3G字节(从虚拟地址0x00 ...

  9. NioEventLoop加载流程分析

    一.我们首先看NioEventLoopGroup创建和初始化过程. EventLoopGroup workEventLoopGroup = new NioEventLoopGroup(new Name ...

最新文章

  1. 移动端网站建设——一如既往地简洁大方
  2. springboot和flowable modeler整合
  3. 【Python爬虫学习笔记6】JSON文件存储
  4. 【学习笔记】12、标准数据类型—列表
  5. python Intel Realsense udp协议 局域网传输实时视频流并通过窗口显示 (opencv压缩解码)
  6. 数据存储方案-闭包表
  7. JavaScript——String转DOM对象解决方案
  8. SAP Spartacus cxFocus增添了refresh Focus功能后的一些考虑
  9. java继承中的 equals + hashCode+toString
  10. mysql显示RMB符号乱码_mysql显示乱码
  11. ROS笔记(21) 地图
  12. mysql point WKB格式 php 解析 unpack
  13. OpenCV读取多幅图片,读取系列图片,读取文件夹中指定图像类型的系列图片
  14. apache poi使用例_Apache POI使用详解
  15. [转]最常用的商务职场英语邮件100个句式
  16. 上网篇:USB网络共享
  17. Android 左右滑动控件
  18. SETCPU超频使用教程
  19. 关于在vue项目中引入pdf.js的跨域问题(已解决)。
  20. C语言详解系列——函数的认识(4)函数的声明与定义,简单练习题

热门文章

  1. Struts2中Action的动态调用方法
  2. vue部分样式无法修改
  3. Java中equals和==
  4. 微信公众号配置后台接入
  5. linux内核部件分析(十)——设备驱动模型之class,linux内核部件分析(十)——设备驱动模型之class...
  6. c++可视化_数据可视化——如何让你的信息图被记住
  7. sorted是python的内置函数吗_Python中的内置sorted()函数
  8. 电子书下载:ASP .NET 4 高级程序设计.第4版
  9. 在PS中如何进行图文互排,且层的使用……
  10. Swift 3到5.1新特性整理