前面几节我们分析了Channel的创建和初始化过程,都是集中在AbstractBootstrap#initAndRegister
方法。在newChannel()
和init(channel)
之后,接着的是便是注册
ChannelFuture regFuture = config().group().register(channel);
初始化的时候配置的NioEventLoopGroup
,调用的是其父类MultithreadEventLoopGroup
的register()
@Override
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
@Override
public EventLoop next() {
return (EventLoop) super.next();
}
next()
方法获取的是一个EventLoop
,调用其父类MultithreadEventExecutorGroup#next()
方法
@Override
public EventExecutor next() {
return chooser.next();
}
chooser
是其成员变量,选择器,用于选择executors
,其初始化的过程其实就是NioEventLoopGroup
的初始过程,查看构造方法,一层一层往上调用,会调用到父类的父类MultithreadEventExecutorGroup#MultithreadEventExecutorGroup)
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
其中初始化了一个参数DefaultEventExecutorChooserFactory.INSTANCE
实例化了一个工厂,记者看构造方法,该工厂最终初始化了chooser
public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
//省略代码
//根据配置的线程数,创建EventExecutor数组
children = new EventExecutor[nThreads];
//实例化数组中具体的的EventExecutor
for (int i = 0; i < nThreads; i ++) {
//省略代码
children[i] = newChild(executor, args);
//省略代码
}
//初始化Executer选择器
chooser = chooserFactory.newChooser(children);
//省略代码
}
查看DefaultEventExecutorChooserFactory#newChooser
,发现是在根据线程数创建EventExecutor
的时候,返回不同的两个选择器
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
//返回一个基于2的幂次方的选择器
return new PowerOfTwoEventExecutorChooser(executors);
} else {
//返回一个通用选择器
return new GenericEventExecutorChooser(executors);
}
}
不难推断其选择器的next()
方法是以这个为基础返回数组中指定的EventExecutor
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
GenericEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}
}
要想知道是具体哪个EventExecutor
,还得查看children[i] = newChild(executor, args);
发现它是一个抽象方法,具体实现类是用户注册的NioEventLoopGroup
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
那么到这里我们发现了其实具体的EventExecutor
其实是NioEventLoop
,查看其register
方法
@Override
public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}
再进一步往下查看发现其调用的是AbstractChannel.AbstractUnsafe#register
,主要干了两件事情,初始化通道的
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
//省略代码
//初始化eventLoop
AbstractChannel.this.eventLoop = eventLoop;
if (eventLoop.inEventLoop()) {
//eventLoop与当前线程相同直接执行
register0(promise);
} else {
//eventLoop与当前线程不同则获取eventLoop的Execute再新增任务执行`register0`
try {
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
}
//省略代码
}
}
register0()
主要做了几件事, 注册,执行Event: HandlerAdded,传递Event: ChannelRegistered,判断是否传递Event: ChannelActive
private void register0(ChannelPromise promise) {
//具体的注册
doRegister();
//执行Event: HandlerAdded
pipeline.invokeHandlerAddedIfNeeded();
//传递Event: ChannelRegistered
pipeline.fireChannelRegistered();
//是否传递Event: ChannelActive
if (isActive()) {
if (firstRegistration) {
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
beginRead();
}
}
}
doRegister()
是一个空方法,应当查看其具体实现AbstractNioChannel
,其中,调用了java底层的时间,注册Selector
并获得selectionKey
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
//注册到java的Selector,未绑定事件,并且获得selectionKey
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
} catch (CancelledKeyException e) {
if (!selected) {
// Force the Selector to select now as the "canceled" SelectionKey may still be
// cached and not removed because no Select.select(..) operation was called yet.
eventLoop().selectNow();
selected = true;
} else {
// We forced a select operation on the selector before but the SelectionKey is still cached
// for whatever reason. JDK bug ?
throw e;
}
}
}
}