Netty源码解读之线程

Netty源码解读之线程

本文主要测试代码如下:



先关注下NioEventLoopGroup和NioEventLoop类关系:



 

在创建NioEventLoopGroup对象之前先执行NioEventLoopGroup父类静态模块,计算出默认的线程个数,电脑配置为四线程,所以默认为8个线程。



进入NioEventLoopGroup构造,并且传递java.nio.channels.spi.SelectorProvider到构造中。




最后调用父类MultithreadEventLoopGroup构造



将默认的线程数传入父类MultithreadEventExecutorGroup构造中




terminationFuture最终实现的是java.util.concurrent.RunnableFuture<V>接口,负责最后释放资源。




回到MultithreadEventExecutorGroup的构造




 

Executor 是线程执行的核心。若为空则需要创建ThreadPerTaskExecutor替代。 

ThreadPerTaskExecutor实现了java.util.concurrent.Executor接口




ThreadPerTaskExecutor中的ThreadFactory成员变量由DefaultThreadFactory生成,DefaultThreadFactory实现了java.util.concurrent.ThreadFactory接口


 

最后所有的EventLoop都由NioEventLoopGroup里的newChild方法实现:
children[i] =newChild(executor, args);并且给EventLoop传入executor和SelectorProvider。



executor最终传到NioEventLoop的父类SingleThreadEventExecutor里。




现在EventLoopGroup和EventLoop创建完成,EventLoop仍未执行,ServerBootstrap完成NioServerSocketChannel的初始化后会时候会异步注册NioServerSocketChannel到Reactor线程的多路复用器上,用来监听ACCEPT。




execute执行方法,若EventLoop未启动,调用启动函数startThread。




在延时任务队列中加入清理任务,调用启动函数doStartThread。




 

doStartThread方法中executor调用execute方法,实际上调用的是ThreadPerTaskExecutor中的execute方法,start一个实际的线程。




在线程中实际运行的run方法SingleThreadEventExecutor.this.run();存在于子类NioEventLoop中,如下图:



这样NioEventLoopGroup(boss)中的NioServerSocketChannel(ACCEPT)线程就运行起来了,实际上bind一个端口就只会启动一个boss线程。NioEventLoopGroup(woker)的工作方式和boss完全一样,启动方式略有不同,要说明白先要梳理下nio socket的创建流程。

 

先关注下NioChannel的类图:


 

 

上面线程中的run方法,真正调用的方法是:processSelectedKeysOptimized(selectedKeys.flip());




依据channel关心的操作执行unsafe操作,ACCEPT和READ都执行unsafe.read();

以NioServerSocketChannel为例,关心ACCEPT操作,同样执行unsafe.read(),如下:




NioServerSocketChannel中的doReadMessages操作如下:




childEventLoopGroup().next()是为了保证所有的连接(NioSocketChannel)会均匀的绑定到8个线程上。




回到NioServerSocketChannel的unsafe.read()

接下来NioServerSocketChannel的pipeline把读到的内容(ClientChannel)送人管道。




因为ServerBootstrap在初始化NioServerSocketChannel的时候为其pipeline加入了ServerBootstrapAcceptor这个handler。




所以调用pipeline的channelRead方法是执行clientChannel(NioSocketChannel)的初始化和注册。

将clientChannel的pipeline加入ChannelInitializer(childHandler),然后执行clientChannel的注册过程




最后NioSocketChannel会调用AbstractNioChannel的doRegister方法,

将clientChannel(NioSocketChannel)注册到eventloop的selector上



同样clientChannel的register采用自身的eventLoop.execute()的异步执行,所以clientChannel所绑定的线程也要开始运行了,数据来到的时候,线程执行unsafe.read(注意:NioSocketChannel的unsafe.read和NioServerSocketChannel的不同)会将数据放入管道pipeline中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值