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)送人管道。

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

所以调用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中。

时间: 2024-08-28 20:31:13

Netty源码解读之线程的相关文章

Netty源码解读(一)概述

Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io.关于Mina已有@FrankHui的Mina系列文章,我正好最近也要做一些网络方面的开发,就研究一下Netty的源码,顺便分享出来了. Netty目前有两个分支:4.x和3.x.4.0分支重写了很多东西,并对项目进行了分包,规模比较庞大,入手会困难一些,而3.x版本则已经被广泛使用.本系列文章针对netty 3.

线程本地变量ThreadLocal源码解读

  一.ThreadLocal基础知识   原始线程现状: 按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步.但是Spring中的各种模板类并未采用线程同步机制,因为线程同步会影响并发性和系统性能,而且实现难度也不小. ThreadLocal在Spring中发挥着重要的作用.在管理request作用域的bean,事务管理,任务调度,AOP等模块中都出现了它的身影. ThreadLocal介绍: 它不是一个线程,而是线程的一个本地化

netty源码分析之揭开reactor线程的面纱(二)

如果你对netty的reactor线程不了解,建议先看下上一篇文章netty源码分析之揭开reactor线程的面纱(一),这里再把reactor中的三个步骤的图贴一下 reactor线程 我们已经了解到netty reactor线程的第一步是轮询出注册在selector上面的IO事件(select),那么接下来就要处理这些IO事件(process selected keys),本篇文章我们将一起来探讨netty处理IO事件的细节 我们进入到reactor线程的 run 方法,找到处理IO事件的代

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)----&gt;第5节: 同线程回收对象

Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第五节: 同线程回收对象 上一小节剖析了从recycler中获取一个对象, 这一小节分析在创建和回收是同线程的前提下, recycler是如何进行回收的 回顾第三小节的demo中的main方法: public static void main(String[] args){ User user1 = RECYCLER.get(); user1.recycle(); User user2 = RECYCLER

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)----&gt;第6节: 异线程回收对象

Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第六节: 异线程回收对象 异线程回收对象, 就是创建对象和回收对象不在同一条线程的情况下, 对象回收的逻辑 我们之前小节简单介绍过, 异线程回收对象, 是不会放在当前线程的stack中的, 而是放在一个WeakOrderQueue的数据结构中, 回顾我们之前的一个图: 8-6-1 相关的逻辑, 我们跟到源码中: 首先从回收对象的入口方法开始, DefualtHandle的recycle方法: public

jdk1.8.0_45源码解读——HashMap的实现

jdk1.8.0_45源码解读——HashMap的实现 一.HashMap概述 HashMap是基于哈希表的Map接口实现的,此实现提供所有可选的映射操作.存储的是<key,value>对的映射,允许多个null值和一个null键.但此类不保证映射的顺序,特别是它不保证该顺序恒久不变.  除了HashMap是非同步以及允许使用null外,HashMap 类与 Hashtable大致相同. 此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能.迭代col

netty 源码分析二

以服务端启动,接收客户端连接整个过程为例分析, 简略分为 五个过程: 1.NioServerSocketChannel 管道生成, 2.NioServerSocketChannel 管道完成初始化, 3.NioServerSocketChannel注册至Selector选择器, 4.NioServerSocketChannel管道绑定到指定端口,启动服务 5.NioServerSocketChannel接受客户端的连接,进行相应IO操作 Ps:netty内部过程远比这复杂,简略记录下方便以后回忆

Netty源码阅读(一) ServerBootstrap启动

Netty源码阅读(一) ServerBootstrap启动 转自我的Github Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.本文讲会对Netty服务启动的过程进行分析,主要关注启动的调用过程,从这里面进一步理解Netty的线程模型,以及Reactor模式. 这是我画的一个Netty启动过程中使用到的主要的类的概要类图,当然是用到的类比这个多得多,而且我也忽略了各个类的继承关系

【转】Netty源码的阅读学习

Netty 源码阅读学习 博客分类: java Netty 背景  最忌工作中接触到Netty相关应用场景,之前看过mima的部分源码,所以最近看了Netty的部分源码和学习其设计思想,做个简单的分享(学习代码为:Netty:3.6.3.FINALE). Netty概述 官方:Netty is an asynchronous event-driven network application framework for rapid development of maintainable high