Netty源码分析第2章(NioEventLoop)---->第1节: NioEventLoopGroup之建立线程执行器

 

Netty源码分析第二章: NioEventLoophtml

 

概述:ide

        经过上一章的学习, 咱们了解了Server启动的大体流程, 有不少组件与模块并无细讲, 从这个章开始, 咱们开始详细剖析netty的各个组件, 并结合启动流程, 将这些组件的使用场景及流程进行一个详细的说明函数

        这一章主要学习NioEventLoop相关的知识, 何为NioEventLoop? NioEventLoop是netty的一个线程, 在上一节咱们建立两个NioEventLoopGroup:oop

EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup();

        这里建立了两个group, 咱们提过这是boss线程组和worker线程组, 其实这两个线程组就至关于两个NioEventLoop的集合, 默认每一个NioEventLoopGroup建立时, 若是不传入线程数, 会建立cpu核数*2个NioEventLoop线程, 其中boss线程经过轮询处理Server的accept事件, 而完成accept事件以后, 就会建立客户端channel, 经过必定的策略, 分发到worker线程进行处理, 而worker线程, 则主要用于处理客户端的读写事件源码分析

        除了轮询事件, EventLoop线程还维护了两个队列, 一个是延迟任务队列, 另外一个是普通任务队列, 在进行事件轮询的同时, 若是队列中有任务须要执行则会去执行队列中的任务学习

        一个NioEventLoop绑定一个selector用于处理多个客户端channel, 可是一个客户端channel只能被一个NioEventLoop处理, 具体关系如图2-0-1所示:this

 

2-0-1spa

        图中咱们看到, 一个NioEventLoopGroup下有多个NioEventLoop线程, 而一个线程能够处理多个channel, 其中有个叫pipeline和handler的东西, 同窗们可能比较陌生, 这是netty的事件传输机制, 每一个pipeline和channel惟一绑定, 这里只须要稍做了解, 以后章节会带你们详细剖析线程

 

        了解了这些概念, 咱们继续以小节的形式对NioEventLoop进行剖析netty

 

第一节:  NioEventLoopGroup之建立线程执行器

 

首先回到第一章最开始的demo, 咱们最初建立了两个线程组:

EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup();

这里, 咱们跟随建立EventLoopGroup的构造方法, 来继续学习NioEventLoopGroup的建立过程

workerGroup为例咱们跟进其构造方法:

public NioEventLoopGroup() { this(0); }

继续跟进this(0):

public NioEventLoopGroup(int nThreads) { this(nThreads, (Executor) null); }

这里的nThreads就是刚传入的0, 继续跟进:

public NioEventLoopGroup(int nThreads, Executor executor) { this(nThreads, executor, SelectorProvider.provider()); }

这里nThreads仍然为0, executornull, 这个execute是用于开启NioEventLoop线程所须要的线程执行器, SelectorProvider.provider()是用于建立selector, 这个以后会讲到

咱们一直跟到构造方法最后:

public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory, final RejectedExecutionHandler rejectedExecutionHandler) { super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory, rejectedExecutionHandler); }

这里调用了父类的构造方法

跟进super, 进入了其父类MultithreadEventExecutorGroup的构造方法中:

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

这里咱们看到, 若是传入的线程数量参数为0, 则会给一个默认值, 这个默认值就是两倍的CPU核数, chooserFactory是用于建立线程选择器, 以后会讲到, 继续跟代码以后, 咱们就看到了建立NioEventLoop的真正逻辑, MultithreadEventExecutorGroup类的构造方法中

跟到MultithreadEventExecutorGroup类的构造方法:

protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) { //代码省略
    if (executor == null) { //建立一个新的线程执行器(1)
        executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); } //构造NioEventLoop(2)
    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) { throw new IllegalStateException("failed to create a child event loop", e); } finally { //代码省略
 } } //建立线程选择器(3)
    chooser = chooserFactory.newChooser(children); //代码省略
}

这边将代码主要分为三个步骤:

1.建立线程执行器

2.建立EventLoop

3.建立线程选择器

这一小节咱们主要剖析第1, 建立线程执行器:

这里有个new DefaultThreadFactory()建立一个DefaultThreadFactory对象, 这个对象做为参数传入ThreadPerTaskExecutor的构造函数,  DefaultThreadFactory顾名思义, 是一个线程工厂, 用于建立线程的, 简单看下这个类的继承关系:

public class DefaultThreadFactory implements ThreadFactory{//类体}

这里继承了jdk底层ThreadFactory, 用于建立线程

咱们继续跟进该类的构造方法:

protected ThreadFactory newDefaultThreadFactory() { return new DefaultThreadFactory(getClass()); }

其中getClass()就是当前类的class对象, 而当前类是NioEventLoopGroup

继续跟进到DefaultThreadFactory的构造方法中:

public DefaultThreadFactory(Class<?> poolType) { this(poolType, false, Thread.NORM_PRIORITY); }

poolTypeNioEventLoopclass对象, Thread.NORM_PRIORITY是设置默认的优先级为5

继续跟构造方法:

public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) { this(toPoolName(poolType), daemon, priority); }

这里的toPoolName(poolType)是将线程组命名, 这里返回后结果是"nioEventLoopGroup"(n头小写), daemonfalse, priority5

继续跟构造方法:

public DefaultThreadFactory(String poolName, boolean daemon, int priority) { this(poolName, daemon, priority, System.getSecurityManager() == null ? Thread.currentThread().getThreadGroup() : System.getSecurityManager().getThreadGroup()); }

 System.getSecurityManager() == null ? Thread.currentThread().getThreadGroup() : System.getSecurityManager().getThreadGroup() 这段代码是经过三目运算建立jdk底层的线程组

继续跟this():

public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) { //省略验证代码 //线程名字前缀
    prefix = poolName + '-' + poolId.incrementAndGet() + '-'; this.daemon = daemon; //优先级
    this.priority = priority; //初始化线程组
    this.threadGroup = threadGroup; }

这里初始化了DefaultThreadFactory的属性, prefixpoolName(也就是nioEventLoopGroup)+'-'+线程组id(原子自增)+'-'

以及初始化了优先级和jdk底层的线程组等属性

 

 

回到最初MultithreadEventExecutorGroup类的构造方法中, 咱们看继续看第一步:

//建立一个新的线程执行器(1)
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(); } }

咱们发现这个类很是简单, 继承了jdkExecutor, 从继承关系中我就能猜测到, 而这个类就是用于开启线程的线程执行器

 

构造方法传入ThreadFactory类型的参数, 这个ThreadFactory就是咱们刚才剖析的DefaultThreadFactory, 这个类继承了ThreadFactory, 因此在构造方法中初始化了ThreadFactory类型的属性

 

咱们再看重写的 execute(Runnable command) 方法, 传入一个任务, 而后由threadFactory对象建立一个线程执行该任务

这个execute(Runnable command)方法, 其实就是用开开启NioEventLoop线程用的, 那么NioEventLoop何时开启的, 后面章节会进行剖析

这样, 经过 executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()) 这种方式就返回了一个线程执行器Executor, 用于开启NioEventLoop线程

 

 

上一节: 绑定端口

下一节: NioEventLoopGroup之NioEventLoop的建立

相关文章
相关标签/搜索