文章目录
netty版本
- 使用的netty版本是
io.netty:netty-all:4.1.33.Final
NioEventLoopGroup
-
继承关系
-
uml图
NioEventLoopGroup调用分析
-
NioEventLoopGroup
无参构造方法分析NioEventLoopGroup构造方法调用 public NioEventLoopGroup() {① this(0); } public NioEventLoopGroup(int nThreads) {② this(nThreads, (Executor) null); } public NioEventLoopGroup(int nThreads, Executor executor) {③ this(nThreads, executor, SelectorProvider.provider()); } public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) {④ super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject()); } 父类 MultithreadEventLoopGroup的构造方法 protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {⑤ super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args); } protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {⑥ this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, args); }
DefaultEventExecutorChooserFactory
-
DefaultEventExecutorChooserFactory
用于选择下一个可用的EventExecutor
, 其内部有两种选择器, 一个是基于位运算,一个是基于取模运算//如果是2的幂次方就使用位运算否则使用取模运算 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() { return executors[idx.getAndIncrement() & executors.length - 1]; } } private static final class GenericEventExecutorChooser implements EventExecutorChooser { private final AtomicInteger idx = new AtomicInteger(); private final EventExecutor[] executors; GenericEventExecutorChooser(EventExecutor[] executors) { this.executors = executors; } @Override public EventExecutor next() { return executors[Math.abs(idx.getAndIncrement() % executors.length)]; } }
MultithreadEventLoopGroup核心代码分析
-
NioEventLoopGroup
无参构造方法默认传入的线程数为0,最终调用的是父类MultithreadEventLoopGroup
的构造方法,当nThreads==0
,如果没有设置系统属性io.netty.eventLoopThreads
(通过-Dio.netty.eventLoopThreads
设置),则此时会使用默认线程个数DEFAULT_EVENT_LOOP_THREADS
DEFAULT_EVENT_LOOP_THREADS的计算规则 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); } } protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) { if (nThreads <= 0) { throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads)); } if (executor == null) { //通过DefaultThreadFactory创建线程 executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); } children = new EventExecutor[nThreads]; for (int i = 0; i < nThreads; i ++) { boolean success = false; try { //初始化nThreads个线程,并存放在children数组中,newChild是抽象方法,由子类实现 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; } } } } } 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); } //为children数组维护一个只读视图readonlyChildren,主要用于迭代。 Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length); Collections.addAll(childrenSet, children); readonlyChildren = Collections.unmodifiableSet(childrenSet); }
-
mac下测试默认线程数,并通过命令确认
@Test public void testThreadNum() { int DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2)); //输出:16. 在超线程的4核Core i7返回NettyRuntime.availableProcessors()返回8 System.out.println(DEFAULT_EVENT_LOOP_THREADS); }
通过命令查看mac cpu信息,4核,8线程。 mac:~ jannal$ sysctl machdep.cpu.core_count machdep.cpu.thread_count machdep.cpu.core_count: 4 machdep.cpu.thread_count: 8
-
NioEventLoopGroup
实现类的newChild
(MultithreadEventLoopGroup
有很多实现类,这里我们主要关注NioEventLoopGroup
这个实现类).可以看出MultithreadEventLoopGroup
中的一个children
其实就是一组NioEventLoop
对象,其实NioEventLoop
就是一个线程,而NioEventLoopGroup
就是一个线程池,NioEventLoop
在后面单独分析@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]); }
ThreadPerTaskExecutor
-
ThreadPerTaskExecutor
实现了jdk的Executor
接口,内部通过ThreadFactory
来启动一个线程,在MultithreadEventLoopGroup
中通过newDefaultThreadFactory()
创建一个DefaultThreadFactory
传入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(); } }
从构造方法可以看出,ThreadPerTaskExecutor
每次执行任务时候都会创建一个Thread
DefaultThreadFactory
-
Netty中默认的
ThreadFactory
,newThread
是通过FastThreadLocalThread
来创建一个Thread。@Override public Thread newThread(Runnable r) { Thread t = newThread(FastThreadLocalRunnable.wrap(r), prefix + nextId.incrementAndGet()); try { if (t.isDaemon() != daemon) { t.setDaemon(daemon); } if (t.getPriority() != priority) { t.setPriority(priority); } } catch (Exception ignored) { // Doesn't matter even if failed to set. } return t; } protected Thread newThread(Runnable r, String name) { return new FastThreadLocalThread(threadGroup, r, name); }
-
构造方法,线程名字的前缀
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)"); } //命名规则poolName-1-xxx prefix = poolName + '-' + poolId.incrementAndGet() + '-'; this.daemon = daemon; this.priority = priority; this.threadGroup = threadGroup; }
总结
NioEventLoopGroup
执行逻辑- 不指定线程数,默认赋值0,此时
nThread=CPU*2
- 创建
ThreadPerTaskExecutor
- 根据
nThread
创建多个NioEventLoop
,并保存在children
数组中 - 根据
children
数组的大小获取下一个Excutor
的选择策略,即选择NioEventLoop
的策略
- 不指定线程数,默认赋值0,此时