jdk的selector(1)

 2023-09-15 阅读 32 评论 0

摘要:在java中如过需要用到Selector来处理Nio的情况下,需要先使用SelectorProvider的provider()方法来取得相应的SelectorProvider。 public static SelectorProvider provider() {synchronized (lock) {if (provider != null)return provider;return AccessController

在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();
}

oracle数据库select语句、这里直接返回了的是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);
}

java listnode、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;
}

 

oracle中number类型对应JAVA。在其构造方法中,会新建一个socket并且得到他的fd和fdVal。

 

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

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

Selector的创建完毕。

 

select java application。 

 

 

 

 

 

java @order注解、 

 

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/58244.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息