大家好,今天我准备死磕NioEventLoopGroup的源码,首先讲下概念,NioEventLoopGroup 它是一个线程池,存放NioEventLoop,一个数组,今天打算先看下这行代码的初始化

 EventLoopGroup bossGroup = new NioEventLoopGroup();

一、初始化

1、时序图:

2.类的关系

3.源码说明:

步骤1:

 EventLoopGroup bossGroup = new NioEventLoopGroup();
//调用链1
public NioEventLoopGroup() {
this(0);
}
//调用链2
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
//调用链3
public NioEventLoopGroup(int nThreads, Executor executor) {
this(nThreads, executor, SelectorProvider.provider());
}
//调用链4
public NioEventLoopGroup(
int nThreads, Executor executor, final SelectorProvider selectorProvider) {
super(nThreads, executor, selectorProvider);
}

如上四个方法是NioEventLoopGroup类的四个构造函数,首先会执行第3行的无参构造函数,然后调用第7行的构造函数,再继续调用第11行的构造函数,这里需要获取一个SelectorProvider,见步骤2,再继续调用第15行的构造函数,这里内部实现调用父类MultithreadEventLoopGroup的构造函数。

步骤2:

 public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return AccessController.doPrivileged(
new PrivilegedAction<SelectorProvider>() {
public SelectorProvider run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}

这里SelectorProvider的静态方法provider获取一个SelectorProvider,全局唯一的,有加锁,依赖底层系统的实现provider不一样,后续另开专题分析;

步骤3:

 protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}

如上是MultithreadEventLoopGroup的构造函数,内部又调用了父类MultithreadEventExecutorGroup的构造函数,继续往下看;

步骤4:

 protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
} 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) {
Thread.currentThread().interrupt();
break;
}
}
}
}
} 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);
}

如上是核心实现的构造函数,代码比较多,我们分段来看下都做了哪些事?

为了方便查看,把代码又粘贴了一遍

if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}

判断线程数是否小于等于0,否则抛出异常。

if (executor == null) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}

第6-8行,会调用子类MultithreadEventLoopGroup的newDefaultThreadFactory方法生成ThreadFactory,这里涉及到java继承初始化的知识,不是调用MultithreadEventExecutorGroup的newDefaultThreadFactory方法,需要注意一下;

 //调用链1,此方法是MultithreadEventLoopGroup类的
1 protected ThreadFactory newDefaultThreadFactory() {
return new DefaultThreadFactory(getClass(), Thread.MAX_PRIORITY);
} //调用链2
public DefaultThreadFactory(Class<?> poolType, int priority) {
this(poolType, false, priority);
}
//调用链3
public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) {
this(toPoolName(poolType), daemon, priority);
} 14 //调用链4
private static String toPoolName(Class<?> poolType) {
if (poolType == null) {
throw new NullPointerException("poolType");
}
String poolName;
Package pkg = poolType.getPackage();
if (pkg != null) {
poolName = poolType.getName().substring(pkg.getName().length() + 1);
} else {
poolName = poolType.getName();
} switch (poolName.length()) {
case 0:
return "unknown";
case 1:
return poolName.toLowerCase(Locale.US);
default:
if (Character.isUpperCase(poolName.charAt(0)) && Character.isLowerCase(poolName.charAt(1))) {
return Character.toLowerCase(poolName.charAt(0)) + poolName.substring(1);
} else {
return poolName;
}
}
} //调用链5
public DefaultThreadFactory(String poolName, boolean daemon, int priority) {
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;
}

如上依次从调用链到调用链5,完成DefaultThreadFactory初始化;

再继续初始化ThreadPerTaskExecutor类

 public ThreadPerTaskExecutor(ThreadFactory threadFactory) {
if (threadFactory == null) {
throw new NullPointerException("threadFactory");
}
this.threadFactory = threadFactory;
}

这里就是new 一个线程工程;

  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) {
Thread.currentThread().interrupt();
break;
}
}
}
}
}

上面初始化了8个(默认,可修改)NioEventLoop, NioEventLoop另外专题分析;

 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);

这里创建一个LinkedHashSet,在把children中的元素全部加进去,然后调用unmodifiableSet,返回一个只读的Chidren,readOnlyChildren;

好了,暂时先分析这么多。

netty之NioEventLoopGroup源码分析二的更多相关文章

  1. netty : NioEventLoopGroup 源码分析

    NioEventLoopGroup 源码分析 1. 在阅读源码时做了一定的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限.为了方便 IDE 查看.跟踪.调试 代码,所以在 github ...

  2. Netty 核心组件 Pipeline 源码分析(二)一个请求的 pipeline 之旅

    目录大纲: 前言 针对 Netty 例子源码做了哪些修改? 看 pipeline 是如何将数据送到自定义 handler 的 看 pipeline 是如何将数据从自定义 handler 送出的 总结 ...

  3. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  4. 《深入探索Netty原理及源码分析》文集小结

    <深入探索Netty原理及源码分析>文集小结 https://www.jianshu.com/p/239a196152de

  5. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  6. Tomcat源码分析二:先看看Tomcat的整体架构

    Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...

  7. 十、Spring之BeanFactory源码分析(二)

    Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...

  8. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  9. 多线程之美8一 AbstractQueuedSynchronizer源码分析<二>

    目录 AQS的源码分析 该篇主要分析AQS的ConditionObject,是AQS的内部类,实现等待通知机制. 1.条件队列 条件队列与AQS中的同步队列有所不同,结构图如下: 两者区别: 1.链表 ...

随机推荐

  1. display的属性值测试

    由于在学习CSS的display的属性值只针对block.inline.inline-block和flex进行过了解,并且自己观察得知列表中li的display属性是list-item,而想要触发BF ...

  2. Python_重写集合

    class Set(object): def __init__(self,data=None): if data == None: self.__data = [] else: if not hasa ...

  3. Java开源生鲜电商平台-推荐系统模块的设计与架构(源码可下载)

    Java开源生鲜电商平台-推荐系统模块的设计与架构(源码可下载) 业务需求: 对于一个B2B的生鲜电商平台,对于买家而言,他需要更加快速的购买到自己的产品,跟自己的餐饮店不相关的东西,他是不关心的,而 ...

  4. jQuery学习之旅 Item2 选择器【二】

    这里接着上一个Item1 把jQuery的选择器讲完.主要有:属性过滤器和子元素过滤器 点击"名称"会跳转到此方法的jQuery官方说明文档. 5. 属性过滤器 Attribute ...

  5. java 基础之 反射技术

    1. java代码 在 java 语言中最核心的就是代码的运行, 按照面向对象的思想,在调用java代码时往往需要先创建对象,再调用方法, 而写在方法中的即所谓的java 代码 一段java代码在程序 ...

  6. Java 面试知识点解析(七)——Web篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  7. Python中使用MongoEngine1

    pymongo来操作MongoDB数据库,但是直接把对于数据库的操作代码都写在脚本中,这会让应用的代码耦合性太强,而且不利于代码的优化管理 一般应用都是使用MVC框架来设计的,为了更好地维持MVC结构 ...

  8. Java Script 读书笔记 (三) 函数

    1. 函数作用域 在函数内部定义的变量,外部无法读取,称为"局部变量"(local variable). 变量v在函数内部定义,所以是一个局部变量,函数之外就无法读取. 函数内部定 ...

  9. cad二次开发--添加对象到模型空间中

    通过实体名来将实体加入到模型空间 AcDbObjectId PostToModelSpace(AcDbEntity *pEnt){ //打开块表 AcDbBlockTable *pBlockTable ...

  10. BZOJ_2882_工艺_后缀数组

    BZOJ_2882_工艺_后缀数组 Description 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且 ...