Netty源码解读之线程

转载 2015年07月07日 18:04:16

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中。

相关文章推荐

Netty 4源码解析:服务端启动

Netty 4源码解析:服务端启动1.基础知识1.1 Netty 4示例因为Netty 5还处于测试版,所以选择了目前比较稳定的Netty 4作为学习对象。而且5.0的变化也不像4.0这么大,好多网上...
  • dc_726
  • dc_726
  • 2015年08月22日 11:29
  • 6648

Netty学习之旅------再谈线程模型之源码分析NioEventLoopGroup、SingleThreadEventExecutor

本文深入细致的分析了Netty NIO的事件模型,从事件模型的初始化(构造的全过程)、核心属性、构造方法、核心入口方法等方面细致分析了NioEventLoopGroup、SingleThreadEve...

Java并发编程中Executor框架

在Java类库中,任务执行的主要抽象不是Thread,而是Executor。 Executor源代码如下: public interface Executor { void execut...

Netty源码解读之线程

  • 2015年09月22日 16:41
  • 656KB
  • 下载

Netty源码解读之线程

Netty源码解读之线程 本文主要测试代码如下: 先关注下NioEventLoopGroup和NioEventLoop类关系:     在创建NioEventLoopGroup对象之前先执行Nio...

Netty线程模型及EventLoop和EventLoopGroup源码解析

1、netty线程模型
  • zxh87
  • zxh87
  • 2017年06月19日 15:29
  • 347

【Netty源码分析】Reactor线程模型

1. 背景1.1. Java线程模型的演进1.1.1. 单线程时间回到十几年前,那时主流的CPU都还是单核(除了商用高性能的小机),CPU的核心频率是机器最重要的指标之一。在Java领域当时比较流行的...

netty源码浅析--线程启动

一直对Java高并发比较感兴趣,最近在学习netty特来记录。        提到netty首先要了解一下什么是Reactor设计模式,在网上找了一下关于Reactor设计模式的介绍,链接在文档的最下...

Netty4 服务端启动源码分析-线程的创建

原文链接:http://xw-z1985.iteye.com/blog/1925013 本文分析Netty中boss和worker的线程的创建过程: 以下代码是服务端的启动代码,线程的...

04storm 源码阅读 storm的进程间消息通信实现clojure端 生成带netty能力的线程

;; Licensed to the Apache Software Foundation (ASF) under one ;; or more contributor license agreeme...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Netty源码解读之线程
举报原因:
原因补充:

(最多只允许输入30个字)