写在这篇博客前!!
为何要写关于Netty的源码博客呢?
因为自己最近初学Netty,熟系了Netty的基本操作以及Netty从BIO 到 NIO的一系列进化过程。梳理了Netty所采用的Reactor模型
但是对Netty内部一系列关于Reactor模型的实现有太多的细节需要梳理。所以决心想写一些关于Netty的博客。为了自己能够更加深入Netty以及更加熟悉Netty。
Netty初始化NioEventLoopGroup
因为自己初次开始写博客,往大家能够指出博客中的不足以及错误,定将及时修正!!感谢
首先从Netty创建两个事件循环组开始写起
创建事件循环组对象
EventLoopGroup workerGroup = new NioEventLoopGroup();
我们是使用默认无参的构造器 创建的 NioEventLoopGroup 但NioEventLoopGroup
内部通过调用一系列带参构造函数以及调用父类的构造函数创建出了NioEventLoop
public NioEventLoopGroup() {
// 调用带参构造函数
// 该参数表示 要创建的NioEventLoopGroup中NioEventLoop的数量
this(0);
}
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory) {
// 该构造函数 指定不同操作系统对多路复用IO的实现方式
public NioEventLoopGroup(int nThreads, Executor executor) {
// SelectorProvider.provider() 不同系统不同的多路复用I/O的具体实现
this(nThreads, executor, SelectorProvider.provider());
}
// 该构造函数提供了一种默认的SelectStrategy工厂
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider) {
this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}
// 该构造指定了线程池的默认拒绝策略
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,final SelectStrategyFactory selectStrategyFactory) {
// RejectedExecutionHandlers.reject() 线程池的拒绝策略处理器 RejectedExecutionHandlers
// 调用父类的构造器 MultithreadEventLoopGroup
super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
// 该构造指定 NioEventLoopGroup 中将创建多少的 NioEventLoop
protected MultithreadEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
Object... args) {
// 调用父类的构造器 MultithreadEventExecutorGroup
// 初始化了NioEventLoopGroup中要创建的NioEventLoop的数量 默认为 CPU核数*2
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, chooserFactory, args);
}
在MultithreadEventExecutorGroup 的构造方法前 做了以下事情
1、指定了默认要创建的NioEventLoop的数量 默认为CPU核数*2
2、指定不同操作系统对多路复用IO的实现方式
3、提供了一种默认的SelectStrategy工厂
4、指定了线程池的默认拒绝策略
最终走到了 MultithreadEventExecutorGroup 的构造方法
该构造主要做了以下事情:
1、创建具体的executor 对象 new ThreadPerTaskExecutor(newDefaultThreadFactory())
2、根据指定要创建NioEventLoop数量创建NioEventLoop
3、初始化chooser,即处理客户端请求分配不同的NioEventLoop来处理
// 开始创建NioEventLoopGroup
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
// 指定线程池创建线程的工厂
/**
该线程工厂指定创建线程的名称 例如 nioEventLoopGroup-2-1
设置创建的线程是否为守护线程
ThreadPerTaskExecutor 重写 execute 方法 该方法也在当前指定的线程工厂中做了具体的实现
*/
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
//创建NioEventLoopGroup中的NioEventLoop
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;
}
}
}
}
}
// 指定选择处理客户端请求的NioEventLoop 的选择策略
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);
}
}
};
// 为每个NioEventLoop 添加监听
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
// 把NioEventLoopGroup 中所有的 NioEventLoop 添加到LinkHashSet集合中去
Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
将MultithreadEventExecutorGroup 构造方法中核心做的三件事单独提出来
创建默认的Executor
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
/**
该方法指定了每次创建线程的名称的前缀
*/
// 该参数是静态的 每次创建新的NioEventLoopGroup 的时候递增
private static final AtomicInteger poolId = new AtomicInteger();
// 该参数非静态的 每次创建新的线程是递增
private final AtomicInteger nextId = new AtomicInteger();
public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {
if (poolName == null) {
throw new NullPointerException("poolName");
}
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
throw new IllegalArgumentException(
"priority: " + priority + " (expected: Thread.MIN_PRIORITY <= priority <= Thread.MAX_PRIORITY)");
}
prefix = poolName + '-' + poolId.incrementAndGet() + '-';
this.daemon = daemon;
this.priority = priority;
this.threadGroup = threadGroup;
}
创建相应的NioEventLoop
这个children = new EventExecutor[nThreads]
children[i] = newChild(executor, args);
newChild 方法 是 MultithreadEventExecutorGroup 内部定义的一个抽象方法 具体的实现有子类实现
跟进具体实现 走进了 NioEventLoopGroup
/**
executor 也在MultithreadEventExecutorGroup 指定了默认的 ThreadPerTaskExecutor
args: args[0]: WindowsSelectorImpl 多路复用I/O的具体实现
args[1]: DefaultSelectStrategyFactory 选择处理客户端请求的NioEventLoop的策略`在这里插入代码片`
args[2]: RejectedExecutionHandler 线程池的拒绝策略
queueFactory: null
*/
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);
}
// 开始创建NioEventLoop
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler,
EventLoopTaskQueueFactory queueFactory) {
/**
这里初始化了两个 taskQueue
在SingleThreadEventLoop 中初始化了 tailTasks 此队列是存放了 外部线程执行的Netty任务
在SingleThreadEventExecutor 中初始化了 taskQueue 此队列是存放了 Netty 要执行的普通任务
如果定义的定时任务 Netty还有 scheduledTaskQueue 队列存放
*/
super(parent, executor, false, newTaskQueue(queueFactory), newTaskQueue(queueFactory),
rejectedExecutionHandler);
if (selectorProvider == null) {
throw new NullPointerException("selectorProvider");
}
if (strategy == null) {
throw new NullPointerException("selectStrategy");
}
provider = selectorProvider;
final SelectorTuple selectorTuple = openSelector();
selector = selectorTuple.selector;
unwrappedSelector = selectorTuple.unwrappedSelector;
selectStrategy = strategy;
}
创建客户端请求分配NioEventLoop的策略
chooser = chooserFactory.newChooser(children);
这里有两种策略
该方法定义在了接口 EventExecutorChooserFactory.newChooser()中
该接口默认只有一个具体的实现
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
isPowerOfTwo(executors.length)
// 该方法用来判断我们每个NioEventLoopGroup中要创建的NioEventLoop的数量是否是2的指数倍
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
// PowerOfTwoEventExecutorChooser的选择策略
// 该策略是对 NioEventLoopGroup 中的长度-1 做与运算 即 从0-executors.length - 1 的循环选择
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
// GenericEventExecutorChooser的选择策略
// 该策略是对NioEventLoopGroup 中的长度做取模运算 即从0-executors.length-1 的循环选择
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}
创建NioEventLoop 调用的父类构造
// 初始化 tailTasks
protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
boolean addTaskWakesUp, Queue<Runnable> taskQueue, Queue<Runnable> tailTaskQueue,
RejectedExecutionHandler rejectedExecutionHandler) {
super(parent, executor, addTaskWakesUp, taskQueue, rejectedExecutionHandler);
tailTasks = ObjectUtil.checkNotNull(tailTaskQueue, "tailTaskQueue");
}
// 初始化 taskQueue
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, Queue<Runnable> taskQueue,
RejectedExecutionHandler rejectedHandler) {
// 在AbstractEventExecutor类中指定 EventExecutorGroup的具体实现 NioEventLoopGroup
super(parent);
this.addTaskWakesUp = addTaskWakesUp; //false
this.maxPendingTasks = DEFAULT_MAX_PENDING_EXECUTOR_TASKS;
this.executor = ThreadExecutorMap.apply(executor, this);
this.taskQueue = ObjectUtil.checkNotNull(taskQueue, "taskQueue");
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
protected AbstractScheduledEventExecutor(EventExecutorGroup parent) {
super(parent);
}
//这里指定了 EventExecutorGroup 的具体实现 即我们创建的 NioEventLoopGroup 对象
protected AbstractEventExecutor(EventExecutorGroup parent) {
this.parent = parent;
}
写在最后
第一次写博客 一定还有许多需要提高进步的地方.
该文章中肯定存在许多自己理解的不到位的地方,还请看到此篇文章的小伙伴们积极指出。我定及时修改并万分感谢
星光不忘赶路人,大家一起进步。