文章目录
- 概述
- 类继承关系
- 源码分析
- 小结
概述
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
这段代码是在使用Netty框架时常见的用法,用于创建两个不同的EventLoopGroup
实例,一个用于处理连接请求(通常称为bossGroup),另一个用于处理连接后的数据流(通常称为workerGroup)。
NioEventLoopGroup
是Netty中用于处理NIO事件的EventLoopGroup
的实现之一。在Netty中,事件循环(EventLoop
)是Netty的核心,负责处理各种事件,比如接收连接、读取数据、写入数据等。
其主要功能和构造函数参数的含义:
-
构造函数参数说明:
- 第一个构造函数参数表示创建的
EventLoop
的数量。对于bossGroup,它通常设置为1,因为它主要用于处理连接请求,而不是处理连接后的数据流。对于workerGroup,通常不设置数量,因为它会根据系统的CPU核心数量自动创建相应数量的EventLoop。
- 第一个构造函数参数表示创建的
-
在构造函数中,
NioEventLoopGroup
会创建一组NioEventLoop
实例。NioEventLoop
是Netty中基于NIO的事件循环实现,它负责处理事件的派发和执行。 -
在
NioEventLoopGroup
的实现中,通常会创建一个或多个线程来执行事件循环中的任务。这些线程会不断地轮询注册在其上的Channel
,处理各种事件。 -
对于bossGroup和workerGroup,它们分别负责处理不同类型的事件,bossGroup主要处理连接请求,而workerGroup主要处理连接后的数据流。
总的来说,NioEventLoopGroup
的源码实现涉及到底层的NIO编程和多线程处理,它提供了一个高效的事件处理机制,使得Netty能够处理大量并发连接和数据流。
类继承关系
源码分析
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup类的构造函数,用于创建一个新的NioEventLoopGroup实例。
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
这个构造函数接受一个参数nThreads
,表示要创建的EventLoop的数量。然后调用了另一个构造函数this(nThreads, (Executor) null)
。
在这个构造函数中,nThreads
表示要创建的EventLoop的数量,通常情况下会根据CPU核心数来确定。参数(Executor) null
表示没有指定额外的Executor,这意味着EventLoopGroup会使用默认的线程工厂来创建线程。
总的来说,这个构造函数的作用是根据指定的线程数量创建一个新的NioEventLoopGroup实例,并使用默认的线程工厂来创建线程。
继续
public NioEventLoopGroup(int nThreads, Executor executor) {
this(nThreads, executor, SelectorProvider.provider());
}
这段代码是NioEventLoopGroup类的构造函数的另一个重载版本,接受三个参数:nThreads
、executor
和SelectorProvider.provider()
。
这个构造函数接受三个参数:
nThreads
表示要创建的EventLoop的数量。executor
表示一个可选的外部Executor,用于执行EventLoop中的任务。如果传入null
,则会使用默认的线程工厂来创建线程。SelectorProvider.provider()
返回一个默认的SelectorProvider,用于创建Selector实例。
然后,这个构造函数调用了另一个构造函数this(nThreads, executor, SelectorProvider.provider())
,将这三个参数传递给它。
这个构造函数的作用是根据指定的线程数量创建一个新的NioEventLoopGroup实例,并允许传入一个可选的Executor,以及一个SelectorProvider,用于创建Selector实例。
继续
public NioEventLoopGroup(
int nThreads, Executor executor, final SelectorProvider selectorProvider) {
this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}
这段代码是NioEventLoopGroup类的构造函数的另一个重载版本,接受四个参数:nThreads
、executor
、selectorProvider
和DefaultSelectStrategyFactory.INSTANCE
。
这个构造函数接受四个参数:
nThreads
表示要创建的EventLoop的数量。executor
表示一个可选的外部Executor,用于执行EventLoop中的任务。如果传入null
,则会使用默认的线程工厂来创建线程。selectorProvider
表示一个SelectorProvider,用于创建Selector实例。DefaultSelectStrategyFactory.INSTANCE
是一个默认的Select策略工厂实例,用于创建Select策略。
然后,这个构造函数调用了另一个构造函数this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE)
,将这四个参数传递给它。
这个构造函数的作用是根据指定的线程数量创建一个新的NioEventLoopGroup实例,并允许传入一个可选的Executor、SelectorProvider,以及一个默认的Select策略工厂实例。
继续
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory) {
super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
这段代码是NioEventLoopGroup类的构造函数的最终版本,接受五个参数:nThreads
、executor
、selectorProvider
、selectStrategyFactory
和RejectedExecutionHandlers.reject()
。
这个构造函数调用了父类构造函数super()
,传递了五个参数:
nThreads
表示要创建的EventLoop的数量。executor
表示一个可选的外部Executor,用于执行EventLoop中的任务。如果传入null
,则会使用默认的线程工厂来创建线程。selectorProvider
表示一个SelectorProvider,用于创建Selector实例。selectStrategyFactory
表示一个Select策略工厂,用于创建Select策略。RejectedExecutionHandlers.reject()
是一个拒绝执行处理器,用于处理任务提交被拒绝的情况。
这个构造函数的作用是根据指定的参数创建一个新的NioEventLoopGroup实例,并设置Executor、SelectorProvider、Select策略工厂和拒绝执行处理器。
继续
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
这段代码是MultithreadEventLoopGroup
类的构造函数,它是MultithreadEventExecutorGroup
类的子类。让我们详细解释这段代码的实现:
这个构造函数通过调用父类构造函数super()
来创建一个新的MultithreadEventLoopGroup
实例,它接受三个参数:
nThreads
表示要创建的EventLoop的数量,如果传入的值为0,则使用默认值DEFAULT_EVENT_LOOP_THREADS
。executor
表示一个可选的外部Executor,用于执行EventLoop中的任务。如果传入null
,则会使用默认的线程工厂来创建线程。args
表示可变参数,用于传递额外的参数给父类构造函数。
在这个构造函数中,首先通过三元运算符判断nThreads
是否为0,如果是,则使用默认值DEFAULT_EVENT_LOOP_THREADS
,否则使用传入的值。然后调用父类构造函数,传递这三个参数。
DEFAULT_EVENT_LOOP_THREADS
private static final int DEFAULT_EVENT_LOOP_THREADS;
static {
// 获取系统属性"io.netty.eventLoopThreads",如果未设置,则使用默认值为可用处理器数的两倍
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
// 如果日志级别为DEBUG,则输出默认的EventLoop线程数
if (logger.isDebugEnabled()) {
logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);
}
}
这段代码是一个静态代码块,用于初始化DEFAULT_EVENT_LOOP_THREADS
这个静态常量。
这个静态代码块主要做了两件事情:
- 通过
SystemPropertyUtil.getInt()
方法获取系统属性"io.netty.eventLoopThreads"
的值,如果未设置,则使用默认值为可用处理器数的两倍。 - 如果日志级别为DEBUG,则通过日志记录框架输出默认的EventLoop线程数。
这个静态代码块的作用是在类加载时初始化DEFAULT_EVENT_LOOP_THREADS
这个静态常量,并根据系统属性设置默认的EventLoop线程数。
总的来说,这个构造函数的作用是根据指定的参数创建一个新的MultithreadEventLoopGroup
实例,并设置EventLoop的数量和Executor。
继续
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
这段代码是MultithreadEventExecutorGroup
类的受保护构造函数,用于创建一个新的MultithreadEventExecutorGroup
实例。
这个构造函数接受三个参数:
nThreads
表示要创建的线程数。executor
表示一个可选的外部Executor,用于执行任务。如果传入null
,则会使用默认的线程工厂来创建线程。args
表示可变参数,用于传递额外的参数给子类的newChild()
方法。
在这个构造函数中,调用了另一个构造函数this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args)
,将这三个参数传递给它,并传递了一个默认的EventExecutor选择器工厂实例DefaultEventExecutorChooserFactory.INSTANCE
。
这个构造函数的作用是根据指定的参数创建一个新的MultithreadEventExecutorGroup
实例,并使用默认的EventExecutor选择器工厂。
继续
这段代码是MultithreadEventExecutorGroup
类的受保护构造函数的具体实现,用于创建一个新的MultithreadEventExecutorGroup
实例。
请看注释
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
// 如果传入的Executor为null,则使用默认的ThreadPerTaskExecutor,并创建一个新的线程工厂
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
// 初始化children数组,用于存储创建的EventExecutor实例
children = new EventExecutor[nThreads];
// 循环创建nThreads个EventExecutor实例
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
// 调用newChild方法创建EventExecutor实例,并将其存储到children数组中
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
// 在创建EventExecutor实例时发生异常,抛出IllegalStateException异常
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
// 如果创建EventExecutor实例失败,则关闭已创建的实例
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.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
}
} catch (InterruptedException interrupted) {
// 如果等待过程中发生中断异常,则将中断信号重新设置
Thread.currentThread().interrupt();
break;
}
}
}
}
}
// 根据chooserFactory创建一个EventExecutor选择器
chooser = chooserFactory.newChooser(children);
// 创建一个监听器,用于监听所有EventExecutor实例的终止事件
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};
// 添加终止事件监听器到每个EventExecutor实例的terminationFuture上
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
// 将children数组转换为不可修改的集合
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
这个构造函数的作用是根据指定的参数创建一个新的MultithreadEventExecutorGroup
实例,并初始化一组EventExecutor
实例。
如果创建EventExecutor
实例失败,则会关闭已创建的实例,并等待它们终止。
最后,创建一个监听器用于监听所有EventExecutor
实例的终止事件,并将children数组转换为不可修改的集合。
重点关注 children[i] = newChild(executor, args);
@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]);
}
这段代码是MultithreadEventLoopGroup
类中的一个重要方法newChild()
的实现,它用于创建新的EventLoop实例。
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
// 从参数数组中获取需要的参数,包括SelectorProvider、SelectStrategyFactory和RejectedExecutionHandler
SelectorProvider selectorProvider = (SelectorProvider) args[0];
SelectStrategyFactory selectStrategyFactory = (SelectStrategyFactory) args[1];
RejectedExecutionHandler rejectedExecutionHandler = (RejectedExecutionHandler) args[2];
// 调用NioEventLoop的构造函数创建一个新的NioEventLoop实例,并返回
return new NioEventLoop(this, executor, selectorProvider, selectStrategyFactory.newSelectStrategy(), rejectedExecutionHandler);
}
这个方法的作用是根据给定的参数创建一个新的EventLoop实例。它首先从参数数组中获取所需的参数,包括SelectorProvider、SelectStrategyFactory和RejectedExecutionHandler,然后调用NioEventLoop的构造函数创建一个新的NioEventLoop实例,并将这些参数传递给它。
总的来说,newChild()
方法的作用是创建一个新的EventLoop
实例,并返回该实例。在MultithreadEventLoopGroup
中,每个EventLoop
实例都负责处理一部分任务。
new NioEventLoop(this, executor, selectorProvider, selectStrategyFactory.newSelectStrategy(), rejectedExecutionHandler)
这段代码是NioEventLoop类的构造函数,用于创建一个新的NioEventLoop实例。
让我们逐步解释这段代码的实现:
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
// 调用父类SingleThreadEventExecutor的构造函数创建一个新的实例
super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
// 检查selectorProvider和selectStrategy是否为null,如果是则抛出NullPointerException
if (selectorProvider == null) {
throw new NullPointerException("selectorProvider");
}
if (strategy == null) {
throw new NullPointerException("selectStrategy");
}
// 初始化成员变量provider为传入的selectorProvider
provider = selectorProvider;
// 调用openSelector()方法打开一个新的Selector,并将返回的SelectorTuple中的selector和unwrappedSelector分别赋值给成员变量selector和unwrappedSelector
final SelectorTuple selectorTuple = openSelector();
selector = selectorTuple.selector;
unwrappedSelector = selectorTuple.unwrappedSelector;
// 初始化成员变量selectStrategy为传入的strategy
selectStrategy = strategy;
}
这个构造函数的作用是初始化NioEventLoop实例的成员变量。
它首先调用父类SingleThreadEventExecutor的构造函数,然后检查传入的selectorProvider和selectStrategy是否为null,如果是则抛出NullPointerException。
接着,将传入的selectorProvider赋值给成员变量provider,并调用openSelector()方法打开一个新的Selector,并将返回的SelectorTuple中的selector和unwrappedSelector分别赋值给成员变量selector和unwrappedSelector。
最后,将传入的strategy赋值给成员变量selectStrategy。
总的来说,这个构造函数的作用是初始化NioEventLoop实例的成员变量,包括selector、unwrappedSelector、provider和selectStrategy
。
重点关注: super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
和 final SelectorTuple selectorTuple = openSelector();
super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler)
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedExecutionHandler) {
// 调用父类SingleThreadEventExecutor的构造函数创建一个新的实例
super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
// 初始化tailTasks,使用newTaskQueue方法创建一个新的任务队列
tailTasks = newTaskQueue(maxPendingTasks);
}
这段代码是SingleThreadEventLoop类的受保护构造函数的实现,用于创建一个新的SingleThreadEventLoop实例。
这个构造函数的作用是创建一个新的SingleThreadEventLoop实例,并初始化它的成员变量。首先调用父类SingleThreadEventExecutor的构造函数,然后使用newTaskQueue方法创建一个新的任务队列tailTasks,并将其赋值给成员变量tailTasks。
总的来说,这个构造函数的作用是初始化SingleThreadEventLoop实例的成员变量,并设置其父类、执行器、任务唤醒标志、最大挂起任务数和拒绝执行处理器
super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler)
这段代码是SingleThreadEventExecutor类的受保护构造函数的实现,用于创建一个新的SingleThreadEventExecutor实例。让我们逐步解释这段代码的实现:
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedHandler) {
// 调用父类构造函数,设置父类EventExecutorGroup
super(parent);
// 设置是否唤醒线程的标志
this.addTaskWakesUp = addTaskWakesUp;
// 设置最大挂起任务数,确保最小为16
this.maxPendingTasks = Math.max(16, maxPendingTasks);
// 应用ThreadExecutorMap,确保executor为非空
this.executor = ThreadExecutorMap.apply(executor, this);
// 初始化任务队列
taskQueue = newTaskQueue(this.maxPendingTasks);
// 设置拒绝执行处理器
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
这个构造函数的作用是创建一个新的SingleThreadEventExecutor实例,并设置其成员变量。它首先调用父类的构造函数,设置父类EventExecutorGroup。然后,根据传入的参数设置是否唤醒线程的标志addTaskWakesUp、最大挂起任务数maxPendingTasks、执行器executor以及拒绝执行处理器rejectedExecutionHandler。
总的来说,这个构造函数的作用是初始化SingleThreadEventExecutor实例的成员变量,并设置其父类、执行器、唤醒线程标志、最大挂起任务数和拒绝执行处理器。
tailTasks = newTaskQueue(maxPendingTasks);
这段代码是SingleThreadEventExecutor类中的一个方法newTaskQueue()
的实现。这个方法用于创建一个任务队列,用于存储待执行的任务。
让我们逐步解释这段代码的实现:
protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {
// 创建一个LinkedBlockingQueue实例作为任务队列,并设置最大容量为maxPendingTasks
return new LinkedBlockingQueue<Runnable>(maxPendingTasks);
}
这个方法的作用是创建一个新的任务队列,用于存储待执行的任务。默认实现使用了LinkedBlockingQueue
,它是一个基于链表的阻塞队列,具有无界的容量,但可以通过maxPendingTasks
参数设置最大容量。如果子类重写这个方法,并且不会对队列执行阻塞调用,可以选择返回一个不支持阻塞操作的更高性能的实现。
总的来说,newTaskQueue()
方法的作用是创建一个任务队列,并返回该队列的实例。
final SelectorTuple selectorTuple = openSelector()
这段代码是NioEventLoop类中的一个方法openSelector()的实现,用于打开一个新的Selector。让我们逐步解释这段代码的实现:
private SelectorTuple openSelector() {
// 声明一个未包装的Selector
final Selector unwrappedSelector;
try {
// 尝试打开一个新的Selector
unwrappedSelector = provider.openSelector();
} catch (IOException e) {
// 打开Selector失败,抛出异常
throw new ChannelException("failed to open a new selector", e);
}
// 如果禁用了选择键集合优化,则返回一个包含未包装的Selector的SelectorTuple
if (DISABLE_KEY_SET_OPTIMIZATION) {
return new SelectorTuple(unwrappedSelector);
}
// 尝试获取SelectorImpl类
Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
return Class.forName(
"sun.nio.ch.SelectorImpl",
false,
PlatformDependent.getSystemClassLoader());
} catch (Throwable cause) {
return cause;
}
}
});
// 如果没有获取到类或者当前的Selector实现不是我们要的实现,则返回一个包含未包装的Selector的SelectorTuple
if (!(maybeSelectorImplClass instanceof Class) ||
!((Class<?>) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) {
if (maybeSelectorImplClass instanceof Throwable) {
Throwable t = (Throwable) maybeSelectorImplClass;
logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t);
}
return new SelectorTuple(unwrappedSelector);
}
// 获取到了SelectorImpl类,尝试使用Unsafe替换SelectionKeySet
final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
// 使用反射设置Selector的selectedKeys和publicSelectedKeys字段为选定的键集
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
// 获取selectedKeys和publicSelectedKeys字段
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
// 如果当前Java版本大于等于9并且具有Unsafe支持,则尝试使用Unsafe替换SelectionKeySet
if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
// 使用Unsafe替换SelectionKeySet
long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
long publicSelectedKeysFieldOffset =
PlatformDependent.objectFieldOffset(publicSelectedKeysField);
if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
PlatformDependent.putObject(
unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
PlatformDependent.putObject(
unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
return null;
}
// 无法检索偏移量,尝试反射作为最后的手段。
}
// 尝试设置字段的访问权限
Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
if (cause != null) {
return cause;
}
cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
if (cause != null) {
return cause;
}
// 设置选定的键集到Selector的selectedKeys和publicSelectedKeys字段
selectedKeysField.set(unwrappedSelector, selectedKeySet);
publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
return null;
} catch (NoSuchFieldException e) {
return e;
} catch (IllegalAccessException e) {
return e;
}
}
});
// 如果出现异常,则返回一个包含未包装的Selector的SelectorTuple
if (maybeException instanceof Exception) {
selectedKeys = null;
Exception e = (Exception) maybeException;
logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, e);
return new SelectorTuple(unwrappedSelector);
}
// 成功设置选定的键集,记录日志并返回一个包含未包装的Selector和SelectedSelectionKeySetSelector的SelectorTuple
selectedKeys = selectedKeySet;
logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector);
return new SelectorTuple(unwrappedSelector,
new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
}
这个方法的作用是打开一个新的Selector,并尝试优化其内部的SelectionKey集合。
首先,它尝试直接打开一个新的Selector,如果失败,则抛出异常。
然后,它检查是否禁用了选择键集合优化。如果没有禁用,则尝试获取sun.nio.ch.SelectorImpl
类,并验证当前Selector的实现是否与获取的类兼容。如果兼容,则尝试使用Unsafe替换SelectionKeySet以提高性能。
最后,返回一个包含未包装的Selector和可能的SelectedSelectionKeySetSelector的SelectorTuple。
小结
NioEventLoopGroup是Netty中用于处理NIO事件的事件循环组。
下面我们总结下NioEventLoopGroup源码:
-
构造函数:NioEventLoopGroup类提供了多个构造函数,用于创建实例。这些构造函数允许指定线程数量、执行器、选择器提供者和选择策略工厂等参数。构造函数内部会调用父类MultithreadEventLoopGroup的构造函数,并设置相关参数。
-
多线程事件循环组:NioEventLoopGroup继承自MultithreadEventLoopGroup类,用于管理多个NioEventLoop实例。它负责创建和管理一组NioEventLoop线程,每个线程处理一个Selector的事件循环。
-
打开新的Selector:NioEventLoopGroup内部使用openSelector()方法来打开一个新的Selector。该方法尝试优化Selector的内部SelectionKey集合,以提高性能。优化过程包括尝试使用Unsafe替换SelectionKeySet,以更有效地处理SelectionKey的集合。
-
任务队列:NioEventLoopGroup内部使用任务队列来存储待执行的任务。默认情况下,它使用LinkedBlockingQueue作为任务队列,但允许子类重写newTaskQueue()方法以选择更高性能的实现。
-
执行器和拒绝策略:NioEventLoopGroup使用执行器来执行任务,并提供拒绝执行处理器来处理任务执行失败的情况。
总的来说,NioEventLoopGroup源码实现了一个用于管理和处理NIO事件的多线程事件循环组,它提供了灵活的构造函数和优化的Selector打开机制,以提高整体性能和并发能力。