EventLoopGroup是一个事件循环组,它管理着多个EventLoop,每个EventLoop都可以看成一个线程池(一般是单个线程,netty的几乎所有EventLoop实现类都是单线程池).
一个EventLoopGroup上会注册多个Channel,实际上它会根据内部EventExecutorChooser的算法,将一个Channel注册到其内部管理的一个具体的EventLoop,此EventLoop线程池处理这个Channel的所有IO事件和业务任务,而其他EventLoop线程池不能处理。
NioEventLoopGroup继承体系
NioEventLoop继承体系
我们一般使用单参数的构造方法 NioEventLoopGroup(n)
或无参构造方法 NioEventLoopGroup()
public NioEventLoopGroup() {
this(0);
}
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
executor是null
selectorProvider是 SelectorProvider.provider()
selectStrategyFactory是 DefaultSelectStrategyFactory.INSTANCE
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory) {
super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
再到父类MultithreadEventLoopGroup,SelectorProvider.provider(),
args参数包含SelectorProvider.provider()、DefaultSelectStrategyFactory.INSTANCE,RejectedExecutionHandlers.reject()
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
再到构造方法
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
再到上级父类MultithreadEventExecutorGroup构造方法
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
最后到这个构造方法,这里开始真正的初始化
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
}
现在构造方法MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object… args) 的各个参数:
new NioEventLoopGroup(n)
中的n,表示要创建的线程数,也是线程池NioEventLoop的个数,因为一个NioEventLoop中只有一个线程(NioEventLoop继承于SingleThreadEventExecutor),note: args中的三个元素
第一个:SelectorProvider是用来创建Selector,
第二个:SelectorProvider.provider()主要基于JDK spi机制发现相应的Provider,
第三个:DefaultSelectStrategyFactory.INSTANCE, 用来创建SelectStrategy,SelectStrategy决定EventExecutor线程池是等待Selector的事件到来还是线程继续空转、还是处理IO事件和业务功能。
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,ThreadPerTaskExecutor的特点是每提交一个任务就创建一个线程去执行,任务会立即执行。
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.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
}
} catch (InterruptedException interrupted) {
// Let the caller handle the interruption.
Thread.currentThread().interrupt();
break;
}
}
}
}
}
//根据构造方法参数传进来的chooserFactory,创建一个EventExecutor选择器,
//这里是基于轮训算法的选择器
chooser = chooserFactory.newChooser(children);
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创建线程终止的回调函数,当所有children终止时,当前的事件循环组能得到通知
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
//将所有EventExecutor包装为不可变集合
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
从ThreadPerTaskExecuto的源码可以看出每提交一个任务就创建一个线程去执行,任务会立即执行。
public final class ThreadPerTaskExecutor implements Executor {
private final ThreadFactory threadFactory;
public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
this.threadFactory = ObjectUtil.checkNotNull(threadFactory, "threadFactory");
}
@Override
public void execute(Runnable command) {
//创建新线程并启动
threadFactory.newThread(command).start();
}
}
newChild()比较简单,就是根据参数new一个EventLoop
@Override
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
EventLoopTaskQueueFactory queueFactory = args.length == 4 ? (EventLoopTaskQueueFactory) args[3] : null;
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2], queueFactory);
}
上面的 chooserFactory.newChooser(children)会根据children数据的长度返回两种不同的EventExecutorChooser,但它们都是基于取余的轮训算法
PowerOfTwoEventExecutorChooser针对children的长度为2的幂次方,它用位运算取余
PowerOfTwoEventExecutorChooser针对children的长度不是2的幂次方,它用常规取余%
运算取余
@Override
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
//确定长度是否为2的幂次方
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
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() {
//和HashMap计算hash桶的原理类似,位运算比较快,(netty尽量在每个可能的地方进行优化,这就是netty的优秀之处的一个体现)
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
private final AtomicLong idx = new AtomicLong();
private final EventExecutor[] executors;
GenericEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
//不是2的幂次方,没法位运算取余常规取余`%`运算取余
return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
}
}