前面幾節我們分析了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;
}
}
}
}