// 开启多路复用器
Selector selector = Selector.open();
/**
* Opens a selector.
*
* <p> The new selector is created by invoking the {@link
* java.nio.channels.spi.SelectorProvider#openSelector openSelector} method
* of the system-wide default {@link
* java.nio.channels.spi.SelectorProvider} object. </p>
*
* @return A new selector
*
* @throws IOException
* If an I/O error occurs
*/
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
// windows下返回默认的WindowsSelectorProviderImpl的实例
// linux下内核版本2.6以前返回poll, 2.6以后返回epoll实例
public class WindowsSelectorProvider extends SelectorProviderImpl {
public WindowsSelectorProvider() {
}
public AbstractSelector openSelector() throws IOException {
return new WindowsSelectorImpl(this);
}
}
WindowsSelectorProviderImpl构造器的实现:
final class WindowsSelectorImpl extends SelectorImpl
{
private final int INIT_CAP = 8;//选择key集合,key包装集合初始化容量
private static final int MAX_SELECTABLE_FDS = 1024;//最大选择key数量
private SelectionKeyImpl channelArray[];//选择器关联通道集合
private PollArrayWrapper pollWrapper;//存放所有文件描述对象(选择key,唤醒管道的源与sink通道)的集合
private int totalChannels;//注册到选择的通道数量
private int threadsCount;//选择线程数
private final List threads = new ArrayList();//选择操作线程集合
private final Pipe wakeupPipe = Pipe.open();//唤醒等待选择操操的管道
private final int wakeupSourceFd;//唤醒管道源通道文件描述
private final int wakeupSinkFd;//唤醒管道sink通道文件描述
private Object closeLock;//选择器关闭同步锁
private final FdMap fdMap = new FdMap();//存放选择key文件描述与选择key映射关系的Map
//子选择器,主要从pollWrapper拉取读写选择key,并更新key通道的就绪操作事件集
private final SubSelector subSelector = new SubSelector();
private long timeout;//超时时间,从pollWrapper拉取文件描述的超时时间
private final Object interruptLock = new Object();//中断同步锁,在唤醒选择操作线程时,用于同步
private volatile boolean interruptTriggered;//是否唤醒等待选择操的线程
private final StartLock startLock = new StartLock();//选择操作开始锁
private final FinishLock finishLock = new FinishLock();//选择操作结束锁
private long updateCount;//已选择key,更新就绪操作事件计数器
static final boolean $assertionsDisabled = !sun/nio/ch/WindowsSelectorImpl.desiredAssertionStatus();
static
{
//加载nio,net资源库
Util.load();
}
}
WindowsSelectorImpl(SelectorProvider var1) throws IOException {
// 调用父类AbstractSelector构造器初始化SelectorProvider
super(var1);
// 设置唤醒sourceFd和sinkFd
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);
}
开启sourceChannel和sinkChannel
private final Pipe wakeupPipe = Pipe.open();
/**
* Opens a pipe.
*
* <p> The new pipe is created by invoking the {@link
* java.nio.channels.spi.SelectorProvider#openPipe openPipe} method of the
* system-wide default {@link java.nio.channels.spi.SelectorProvider}
* object. </p>
*
* @return A new pipe
*
* @throws IOException
* If an I/O error occurs
*/
public static Pipe open() throws IOException {
return SelectorProvider.provider().openPipe();
}
public Pipe openPipe() throws IOException {
return new PipeImpl(this);
}
PipeImpl(SelectorProvider var1) throws IOException {
try {
AccessController.doPrivileged(new PipeImpl.Initializer(var1));
} catch (PrivilegedActionException var3) {
throw (IOException)var3.getCause();
}
}
// 在本地主机上建立两个channel,并利用一个随机产生的long进行验证
private class Initializer implements PrivilegedExceptionAction<Void> {
private final SelectorProvider sp;
private Initializer(SelectorProvider var2) {
this.sp = var2;
}
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) {
;
}
}
}
}
implRegister方法:
protected void implRegister(SelectionKeyImpl selectionkeyimpl)
{
//同步关闭锁,以防在注册的过程中,选择器被关闭
synchronized(closeLock)
{
if(pollWrapper == null)
//文件描述包装集合为null,即选器已关闭
throw new ClosedSelectorException();
growIfNeeded();//
channelArray[totalChannels] = selectionkeyimpl;//添加到选择器通道集合
selectionkeyimpl.setIndex(totalChannels);//设置key在选择器通道集合的索引
fdMap.put(selectionkeyimpl);//添加选择key到文件描述fdMap
keys.add(selectionkeyimpl);//添加key到key集合
//将选择key添加到文件描述信息及关注操作事件包装集合pollWrapper
pollWrapper.addEntry(totalChannels, selectionkeyimpl);
totalChannels++;//通道计数器自增
}
}