EventLoopGroup
在编写Netty服务端之前,我们一定会创建两个EventLoopGroup
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
这两个对象是Netty的核心对象,整个Netty的运作都是依赖于他们。bossGroup用于接收TCP请求,它会将接收到的请求交给workerGroup,workerGroup来真正的建立连接并完成之后的具体处理。
EventLoopGroup是一个事件循环组(本质上是一个线程组),包含有多个EventLoop,用于Channel的注册(一般情况下是多个,取决于EventLoop的具体实现),在事件循环中进行选择(和selector相关)。
以EventLoopGroup的常用实现类NioEventLoopGroup为例
NioEventLoopGroup拥有很多构造方法,这些构造方法中经常会有的[int nThreads]参数,表示你可以指定线程组创建的线程数,默认情况下创建CPU物理核心数 * 2个线程,这是Netty对于现在支持超线程CPU的优化,尽可能发挥硬件多线程处理的优势。
通过其父类MultithreadEventLoopGroup代码可看出:
private static final int DEFAULT_EVENT_LOOP_THREADS;
static {
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
if (logger.isDebugEnabled()) {
logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
}
}
/**
* @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor, Object...)
*/
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
DEFAULT_EVENT_LOOP_THREADS是在静态代码块中赋值的,当没有在环境配置中指定io.netty.eventLoopThreads数值的时候,将通过NettyRuntime.availableProcessors()来获取计算机物理核心数并*2。
一直跟进代码到MultithreadEventExecutorGroup的构造方法:
/**
* Create a new instance.
*
* @param nThreads the number of threads that will be used by this instance.
* @param executor the Executor to use, or {@code null} if the default should be used.
* @param chooserFactory the {@link EventExecutorChooserFactory} to use.
* @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call
*/
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
// TODO: Think about if this is a good exception type
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
if (!success) {
for (int j = 0; j < i; j ++) {
children[j].shutdownGracefully();
}
for (int j = 0; j < i; j ++) {
EventExecutor e = children[j];
try {
while (!e.isTerminated()) {
e.awaitTermin