NioEventLoopGroup
开始流水账式分析:
NioEventLoopGroup(自身)
先看看常用的
new NioEventLoopGroup();
NioEventLoopGroup
这个类中本身没有去定义任何成员变量
从无参构造方法不断调用,
无参构造默认传输的线程数是0
,创建了一个null
的Executor
继续传递
其中涉及Java NIO的 selector、netty定义的选择器生成工厂等。
另外再看。
最后到达:
public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory) {
super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory,
RejectedExecutionHandlers.reject());
}
MultithreadEventLoopGroup(父类)
由super
去看父类(抽象类)
: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);
}
}
紧接NioEventLoopGroup方法调用的super,到达的是此类中的一个方法:
/**
* @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor,
* EventExecutorChooserFactory, Object...)
*/
protected MultithreadEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, chooserFactory, args);
}
注意:
NioEventLoopGroup
中:
MultithreadEventLoopGroup
中:
方框中的三个参数:selectorProvider
、selectStrategyFactory
, RejectedExecutionHandlers.reject()
均放在args
这个里面传递,后面会用到!
先看一下常量 DEFAULT_EVENT_LOOP_THREADS
:
Runtime.getRuntime().availableProcessors()
//返回当前虚拟机可用核心数
可见 DEFAULT_EVENT_LOOP_THREADS
:常量、线程数的默认值、为当前虚拟机可用核心数*2
所以对于
/**
* @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor, Object...)
*/
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
如果没有初始化时没有传线程数/线程数为0,那么默认以虚拟机可用核心数*2作为线程数
如果不为0,则以此为线程数去创建。
MultithreadEventLoopGroup这里也使用了super
,还得看其父类MultithreadEventExecutorGroup
MultithreadEventExecutorGroup(父类)
MultithreadEventExecutorGroup
定义了五个:
private final EventExecutor[] children;//这个Group所拥有的执行器数组
private final Set<EventExecutor> readonlyChildren;//执行器数组的只读Set集合
private final AtomicInteger terminatedChildren = new AtomicInteger();
private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
private final EventExecutorChooserFactory.EventExecutorChooser chooser;//一个由选择器工厂生成出来的选择器
进入到了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 args arguments which will passed to each {@link #newChild(Executor, Object...)} call
*/
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args);
}
接收到线程数量
、执行器
、和args(包含了三个参数传递)
增加了一个DefaultEventExecutorChooserFactory.INSTANCE
实例放在参数中
调用其实际的生成线程方法:
/**
* Create a new instance. 创建了一个实例
*
* @param nThreads the number of threads that will be used by this instance.
* nThreads表示这个实例即将用到的线程数
* @param executor the Executor to use, or {@code null} if the default should be used.
* executor 如果是默认值的话就应该是null
* @param chooserFactory the {@link EventExecutorChooserFactory} to use.
* chooserFactory 属于EventExecutorChooserFactory类型
* 传递的是上面给的DefaultEventExecutorChooserFactory
* 是因为DefaultEventExecutorChooserFactory这个类实现了EventExecutorChooserFactory接口
*
* @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call
*/
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
//netty 的ObjectUtil工具类中定义的方法,
//作用是检查给出的参数是否合格,其实就是判断nThreads这个值
//要是<=0,则抛出IllegalArgumentException异常
checkPositive(nThreads, "nThreads");
//如果传递的executor 为null,也就是NioEventLoopGroup无参传递来的默认值
//则给它赋值,
if (executor == null) {
//给线程执行器内传递了netty定义的线程工厂由它去创建一个线程
//此时的executor 就是负责启动Reactor的线程(至于为什么?需要看NioEventLoop)
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
//成员变量children 是一个事件执行器数组,此时为根据线程数量定义数组大小
children = new EventExecutor[nThreads];
//for循环遍历挨个儿创建Executor放进children数组中
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
children[i] = newChild(executor, args);//调用实现类(NioEventLoopGroup)创建
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;
}
}
}
}
}
//将创建好的所有执行器全都给选择器工厂,选择器工厂加工生成一个选择器
chooser = chooserFactory.newChooser(children);
//涉及netty自建的Futrue类需要另外研究
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};
for (EventExecutor e: children) {//监听执行器
e.terminationFuture().addListener(terminationListener);
}
//添加执行器组的只读集合
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
DefaultEventExecutorChooserFactory
netty所提供的默认的 事件执行器选择工厂 类
通过其定义的DefaultEventExecutorChooserFactory.INSTANCE
静态可以直接获取实例
实现了EventExecutorChooserFactory
接口
EventExecutorChooserFactory
EventExecutorChooserFactory
接口定义了事件选择器工厂
事件选择器工厂
的作用就是生成一个新的事件选择器
- 声明了
创建新的选择器
的方法 - 声明了
选择器
DefaultEventExecutorChooserFactory是EventExecutorChooserFactory 唯一的实现类
DefaultEventExecutorChooserFactory
生成何种选择器的规则
@Override
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {//是则选择 PowerOfTwoEventExecutorChooser选择器
return new PowerOfTwoEventExecutorChooser(executors);
} else {//否则选择 GenericEventExecutorChooser选择器
return new GenericEventExecutorChooser(executors);
}
}
//`isPowerOfTwo`判断`执行器的个数`是否是`2的幂次`
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
DefaultEventExecutorChooserFactory
定义了两种选择器
,每个选择器都具有一个next()
方法,在执行器数组中以特定方式选取一个执行器返回
。
//2次幂事件执行器选择器
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 {
// Use a 'long' counter to avoid non-round-robin behaviour at the 32-bit overflow boundary.
// The 64-bit long solves this by placing the overflow so far into the future, that no system
// will encounter this in practice.
private final AtomicLong idx = new AtomicLong();
private final EventExecutor[] executors;
GenericEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override
public EventExecutor next() {
return executors[(int) Math.abs(idx.getAndIncrement() % executors.length)];
}
}
关于DefaultThreadFactory
类中的线程工厂方法
//netty提供的默认线程工厂方法
//线程池名称、是否为守护线程、优先级、线程组
public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
ObjectUtil.checkNotNull(poolName, "poolName");
//优先级不能小于Thread定义的最小值,大于Thread定义的最大值
//否则抛出异常
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
throw new IllegalArgumentException(
"priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
}
//DefaultThreadFactory的成员变量,prefix:前缀 ,也就是平时看到的真正的线程名称
prefix = poolName + '-' + poolId.incrementAndGet() + '-';
this.daemon = daemon;
this.priority = priority;
this.threadGroup = threadGroup;
}
在创建线程的过程中,newChild
是MultithreadEventExecutorGroup中定义的一个抽象方法:
/**
* Create a new EventExecutor which will later then accessible via the {@link #next()} method. This method will be
* called for each thread that will serve this {@link MultithreadEventExecutorGroup}.
*
*/
protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;
转了一大圈,还得记住super只是调用父类方法,这个时候我们还在NioEventLoopGroup
中呢
重写的newChild
对于NioEventLoopGroup
而言,它是MultithreadEventExecutorGroup的子类,并且自己重写了newChild
这个方法:
@Override
//上述中,args中存有三个参数
//selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject()
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
//这里0、1、2三个下标直接取
SelectorProvider selectorProvider = (SelectorProvider) args[0];//
SelectStrategyFactory selectStrategyFactory = (SelectStrategyFactory) args[1];
RejectedExecutionHandler rejectedExecutionHandler = (RejectedExecutionHandler) args[2];
EventLoopTaskQueueFactory taskQueueFactory = null;
EventLoopTaskQueueFactory tailTaskQueueFactory = null;
int argsLength = args.length;
if (argsLength > 3) {
taskQueueFactory = (EventLoopTaskQueueFactory) args[3];
}
if (argsLength > 4) {
tailTaskQueueFactory = (EventLoopTaskQueueFactory) args[4];
}
//NioEventLoopGroup创建的执行器是NioEventLoop
return new NioEventLoop(this, executor, selectorProvider,
selectStrategyFactory.newSelectStrategy(),
rejectedExecutionHandler, taskQueueFactory, tailTaskQueueFactory);
}
总结:
NioEventLoopGroup
的无参构造会默认创建i=虚拟机可用核心数*2
个EventExecutor
,若指定了线程数量则按照指定的数量NioEventLoopGroup
通过调用i
次newChild
完成i
个EventExecutor(NioEventLoop)的创建- 在创建完成后还会根据执行器集合生成合适的
选择器
……未完