《Java 源码分析》:Java NIO 之 Selector(第二部分selector.select())
上篇博文《Java 源码分析》:Java NIO 之 Selector(第一部分Selector.open())从源码的角度主要介绍了Selector.open()这个方法背后主要做了什么,发生了什么。
本篇就是第二部分:从源码的角度来看下selector.select()背后做了些什么,怎么做的
在看这篇博文之前,希望你已经阅读了上一篇博文:《Java 源码分析》:Java NIO 之 Selector(第一部分Selector.open())。因为这篇博文是在上篇博文的基础上来进行介绍的。
为了更好的方便理解这篇博文所介绍的内容,我们先来回顾下上篇博文中所介绍的内容。
Selector selector = Selector.open();这行代码简单来说:实例化了一个WindowSelectorImpl类的对象。并且在windows下通过两个链接的socketChannel实现了Pipe。
知道上面一点知识就更加方便的来理解了。下面开始详细的介绍。
selector.select() 介绍
selector.select()在Selector类中此方法是一个抽象的。
如下:
public abstract int select() throws IOException;
函数功能(根据源码上的注释翻译而来):选择一些I/O操作已经准备好的管道。每个管道对应着一个key。这个方法 是一个阻塞的选择操作。当至少有一个通道被选择时才返回。当这个方法被执行时,当前线程是允许被中断的。
除了这个方法,还有两个重载方法,如下
1、select(long timeout)
public abstract int select(long timeout)
throws IOException;
select(long timeout)和select()一样,除了最长会阻塞timeout毫秒(参数)。
这个方法并不能提供精确时间的保证,和当执行wait(long timeout)方法时并不能保证会延时timeout道理一样。
这里的timeout说明如下:
如果 timeout为正,则select(long timeout)在等待有通道被选择时至多会阻塞timeout毫秒
如果timeout为零,则永远阻塞直到有至少一个通道准备就绪。
- timeout不能为负数
2、selectNow()
public abstract int selectNow() throws IOException;
这个方法与select()的区别在于,是非阻塞的,即当前操作即使没有通道准备好也是立即返回。只是返回的是0.
值得注意的是:调用这个方法会清除所有之前执行了wakeup方法的作用。
以上就是select()以及其两个重载方法的一点说明。
下面来看select()方法在其子类的具体实现
在上篇博文中我们通过源码的角度知道Selector selector = Selector.open();代码中的selector实际是指向的是其子类WindowsSelectorImpl 的对象实例。
因此在 我们执行 selector.select()方法时,实际上时调用的是 WindowsSelectorImpl 中的select()方法
在找这个函数的时候,觉得有必要说下Selector, WindowsSelectorImpl 之间的继承关系:
- WindowsSelectorImpl 的直接父类是 SelectorImpl(select方法在这个里面实现);
- SelectorImpl 的直接父类是 AbstractSelector
- AbstractSelector 的直接父类是 Selector.
以上就是他们的继承关系,其中select()方法是在 SelectorImpl类中进行实现的。
——SelectorImpl.java中的部分代码如下———–
public int select(long timeout)
throws IOExcepti