使用:bossGroup = new NioEventLoopGroup();
构造函数
NioEventLoopGroup--->MultithreadEventLoopGroup。
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
// 如果没有指定executor
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i++) {
boolean success = false;
try {
// 初始化每一个executor
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
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);
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);
}
NioEventLoopGroup包含着一个数组NioEventLoop[] childs,NioEventLoop是netty对线程和seletor的包装。一个NioEventLoop绑定一个线程和一个seletor。这样NioEventLoop就有了注册监听io事件以及开启线程的能力。
我们重点看一下两个地方。
构建executor
if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
看一下ThreadPerTaskExecutor 。逻辑很简单,接收到提交任务,就调用线程池工厂创建一个线程运行任务。
public final class ThreadPerTaskExecutor implements Executor {
private final ThreadFactory threadFactory;
public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
if (threadFactory == null) {
throw new NullPointerException("threadFactory");
}
this.threadFactory = threadFactory;
}
@Override
public void execute(Runnable command) {
threadFactory.newThread(command).start();
}
}
我们再看特别线程池工厂的newThread方法,这里构建的是FastThreadLocalThread。这里暂时不分析
protected Thread newThread(Runnable r, String name) {
return new FastThreadLocalThread(threadGroup, r, name);
}
构建 EventExecutor
// 初始化每一个executor
children[i] = newChild(executor, args);
newChild方法。主要参数executor、selector、选择策略、拒绝策略
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
看一下NioEventLoop->SingleThreadEventExecutor的构造方法。看名字就知道,eventloop就是一个单线程的线程池。构造方法主要是构建出父类线程池,然后打开selector。
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
if (selectorProvider == null) {
throw new NullPointerException("selectorProvider");
}
if (strategy == null) {
throw new NullPointerException("selectStrategy");
}
provider = selectorProvider;
selector = openSelector();
selectStrategy = strategy;
}
SingleThreadEventExecutor的构造
protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
boolean addTaskWakesUp, int maxPendingTasks,
RejectedExecutionHandler rejectedHandler) {
super(parent);
this.addTaskWakesUp = addTaskWakesUp;
this.maxPendingTasks = Math.max(16, maxPendingTasks);
this.executor = ObjectUtil.checkNotNull(executor, "executor");
taskQueue = newTaskQueue(this.maxPendingTasks);
rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
}
主要是赋值了executor、拒绝策略,队列最大数,构建了一个任务队列(Netty-无锁队列-1_xiaoxishuaidaile的博客-CSDN博客)。这个executor就是NioEventLoopGroup中构建的executor,默认值是ThreadPerTaskExecutor。
我们先一下这个executor的使用,我们经常能看到netty类似的代码。
eventLoop.execute(new Runnable() {
/*
*...
*/
});
最终都进入了SingleThreadEventExecutor.execute
public void execute(Runnable task) {
if (task == null) {
throw new NullPointerException("task");
}
boolean inEventLoop = inEventLoop();
if (inEventLoop) {
addTask(task);
} else {
startThread();
addTask(task);
if (isShutdown() && removeTask(task)) {
reject();
}
}
if (!addTaskWakesUp && wakesUpForTask(task)) {
wakeup(inEventLoop);
}
}
看一下这个inEventLoop这个判断
public boolean inEventLoop(Thread thread) {
// 判断当前线程是不是eventLoop绑定线程
return thread == this.thread;
}
startThread最终进入doStartThread。这里的executor就是上面的executor,默认就是来一个任务就开启一个新线程运行此任务,然后这里还有eventLoop和线程绑定的逻辑和selector线程相关逻辑
private void doStartThread() {
assert thread == null;
executor.execute(new Runnable() {
@Override
public void run() {
// 线程绑定
thread = Thread.currentThread();
if (interrupted) {
thread.interrupt();
}
boolean success = false;
updateLastExecutionTime();
try {
// selector线程开启
SingleThreadEventExecutor.this.run();
success = true;
} catch (Throwable t) {
logger.warn("Unexpected exception from an event executor: ", t);
} finally {
。。。
。。。
addTask就是把任务加到任务队列中。