码迷,mamicode.com
首页 > 编程语言 > 详细

Netty源码解读之线程

时间:2014-08-28 13:20:19      阅读:318      评论:0      收藏:0      [点我收藏+]

标签:netty nio 线程

Netty源码解读之线程

本文主要测试代码如下:



bubuko.com,布布扣


先关注下NioEventLoopGroup和NioEventLoop类关系:


bubuko.com,布布扣

 

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


bubuko.com,布布扣


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


bubuko.com,布布扣


最后调用父类MultithreadEventLoopGroup构造

bubuko.com,布布扣


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


bubuko.com,布布扣


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


bubuko.com,布布扣


回到MultithreadEventExecutorGroup的构造


bubuko.com,布布扣


 

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


bubuko.com,布布扣


 

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


bubuko.com,布布扣


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


bubuko.com,布布扣

 

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


bubuko.com,布布扣

bubuko.com,布布扣


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


bubuko.com,布布扣


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


bubuko.com,布布扣

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


bubuko.com,布布扣


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


bubuko.com,布布扣

bubuko.com,布布扣


 

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


bubuko.com,布布扣


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


bubuko.com,布布扣


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

 

先关注下NioChannel的类图:


bubuko.com,布布扣 

 

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

bubuko.com,布布扣

bubuko.com,布布扣



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

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


bubuko.com,布布扣


NioServerSocketChannel中的doReadMessages操作如下:


bubuko.com,布布扣


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

bubuko.com,布布扣

bubuko.com,布布扣


回到NioServerSocketChannel的unsafe.read()

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


bubuko.com,布布扣


由于NioServerSocketChannel在bind的时候初始化的ChannelInitializer中给pipeline加入的handler为ServerBootstrapAcceptor。


bubuko.com,布布扣


所以调用pipeline的channelRead方法是执行clientChannel(NioSocketChannel)的注册过程。

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


bubuko.com,布布扣


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

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


bubuko.com,布布扣

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

Netty源码解读之线程

标签:netty nio 线程

原文地址:http://blog.csdn.net/handsome_926/article/details/38896011

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!