1、初始化EventLoopGroup,并设置接受新socket的线程数量。
在创建接受新socket的EventLoopGroup时
EventLoopGroup bossGroup = new NioEventLoopGroup(8);
NioEventLoopGroup(MultithreadEventLoopGroup).<init>(int nThreads, ThreadFactory threadFactory, Object... args)
MultithreadEventLoopGroup类根据nThreads参数或者默认数值来创建线程。
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));
默认线程数量为Runtime.getRuntime().availableProcessors() * 2.
2、注册NioServerSocketChannel
ServerBootstrap(AbstractBootstrap<B,C>).bind(int)
在ServerBootstrap绑定本地端口时,ServerBootstrap(AbstractBootstrap<B,C>).initAndRegister() 初始化和注册 NioServerSocketChannel .
注册ChannelFuture regFuture = group().register(channel); 使EventLoopGroup与NioServerSocketChannel相关联。
MultithreadEventExecutorGroup$PowerOfTwoEventExecutorChooser 在①初始化EventLoopGroup时的内部类中,使NioServerSocketChannel与EventLoopGroup相关联。
private final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser
{
@Override
public EventExecutor next()
{
return children[childIndex.getAndIncrement() & children.length - 1];
}
}
AbstractNioMessageChannel$NioMessageUnsafe(AbstractChannel$AbstractUnsafe).register(EventLoop, ChannelPromise)
在AbstractChannel抽象类中,有AbstractChannel内部类.
public final void register(EventLoop eventLoop, final ChannelPromise promise)
{
if (eventLoop == null)
{
throw new NullPointerException("eventLoop");
}
if (isRegistered())
{
promise.setFailure(new IllegalStateException("registered to an event loop already"));
return;
}
AbstractChannel.this.eventLoop = eventLoop;//NioServerSocketChannel 引用EventLoopGroup,在这里相关联
if (eventLoop.inEventLoop())
{
register0(promise);//如果当前线程和EventLoopGroup是同一个线程,就执行关联。否则,则开一个线程执行关联。
} else
{
try {
eventLoop.execute(new OneTimeTask()
{
@Override
public void run()
{
register0(promise);
}
});
}
}
}
private void register0(ChannelPromise promise)
{
try
{
// check if the channel is still open as it could be closed in the mean time when the register
// call was outside of the eventLoop
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
doRegister();
neverRegistered = false;
registered = true;
safeSetSuccess(promise);
pipeline.fireChannelRegistered();
// Only fire a channelActive if the channel has never been registered. This prevents firing
// multiple channel actives if the channel is deregistered and re-registered.
if (firstRegistration && isActive()) {
pipeline.fireChannelActive();
}
}
}
NioServerSocketChannel(AbstractNioChannel).doRegister()
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
selectionKey = javaChannel().register(eventLoop().selector, 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;
}
}
}
}
至此,在服务器启动时,建立一个线程池来关联新socket的链接。