NIO线程模型


上一篇说的是基于操作系统的IO处理模型,那么这一篇来介绍下服务器端基于IO模型和自身线程的处理方式。

一、传统阻塞IO模型下的线程处理模式

这种处理模型是基于阻塞IO进行的,上一篇讲过,阻塞IO会阻塞每一个IO操作,直到事件就绪,下面来看下阻塞IO下的服务端线程模型:

图1

如上图所示,该线程模型基于阻塞IO模型实现,针对每个请求都需要抽出来一个线程进行处理读入数据、业务处理数据、返回响应结果给客户端,这个过程中读、写操作均会阻塞,且跟业务处理串行执行,该模式下,并发量过大时会大量创建线程,发生的大量上下文切换,从而导致CPU资源占用过大,当连接建立后,若当前线程暂无可读数据,则线程会一直阻塞在读操作上,造成线程资源浪费,即便使用线程池进行优化,虽然避免了大量创建线程,但也会出现线程资源浪费的问题,高并发下可能会造成排队、响应不及时的问题。

具体BIO服务器的实现参考:SocketChannel与BIO服务器

二、基于IO多路复用模型下的Reactor线程模型

利用操作系统IO多路复用模型实现,Java对其调用进行了封装(select等),这里先不探讨怎么利用java的api去调用,先来看看它的基本流程是怎样的,Reactor模式下的县线程模型又会根据线程数量、线程池数量的不同,细分了三种线程模型。

2.1:单Reactor单线程模型

这是最简单的Reactor模型,整个过程中的事件处理全部发生在一个线程里:

图2

上图示意就是个简单的IO多路复用单Reactor单线程处理模型,流程如下:

①Reactor对象通过select监听客户端的请求事件,收到事件消息后通过dispatch进行任务分发。

②如果是建连请求,则交由Acceptor对象处理连接请求,然后创建一个Handler对象继续完成后续处理

③若不是建连请求,则dispatch会调用对应连接的Handler进行处理,Handle负责完成连接成功后的后续处理(读操作、写操作、业务处理等)

此模型很简单,易于理解,但是存在一定的问题,比如单线处理程模型下,无法发挥多核CPU的性能,如果Handler上的业务处理很慢,则意味着整个程序无法处理其他连接事件,造成性能问题。

适用于业务处理快速、客户端连接较少的情况。

2.2:单Reactor多线程模型

相较于上面的模型,对业务处理模块进行了异步处理,流程图如下:

图3

上图示意属于单Reactor多线程处理模型,流程如下:

①Reactor对象通过select监听客户端的请求事件,收到事件消息后通过dispatch进行任务分发。

②如果是建连请求,则交由Acceptor对象处理连接请求,然后创建一个Handler对象继续完成后续处理

③若不是建连请求,则dispatch会调用对应连接的Handler进行处理,Handle负责完成连接成功后的读操作,读出来数据后的业务处理部分交由线程池异步处理,业务处理完成后发送给Handler处理完成的消息,然后再由Handler发送处理响应信息给对应的Client。

本模型充分利用了多核CPU的处理能力,降低了由业务处理引起的性能问题,Reactor线程仅负责接收连接、读写操作。但是Reactor除了负责连接处理外仍然负责读写操作,大量的请求下仍然可能仍然存在性能问题。

2.3:主从Reactor多线程模型

这个模型中将会独立出另一个Reactor对象来处理非连接处理的其他处理,命名为从Reactor(SubReactor),流程图如下:

图4

上图示意属于主从Reactor多线程处理模型,流程如下:

①主Reactor对象(MainReactor)通过select监听客户端的连接事件,收到连接事件后交由Acceptor处理。

②Acceptor处理完成后,MainReactor将此连接分配给SubReactor处理,SubReactor将此连接加入连接队列进行事件监听并建立Handler进行后续的各种操作,同上面的模型一致,SubReactor会监听新的事件,如果有新的事件发生,则调用Handler进行相应的处理。

③Handler读出来数据后的业务处理部分交由线程池异步处理,业务处理完成后发送给Handler处理完成的消息,然后再由Handler发送处理响应信息给对应的Client。

该模型存在两个线程分别处理Reactor事件,主线程只负责处理连接事件,子线程只负责处理读写事件,这样主线程可以处理更多的连接,而不用关心子线程里的读写处理是否会影响到自己。目前这种模型被广泛使用在各种项目中(如Netty、Memcached等)。

以上的线程模型都是基于同步IO,异步IO这里不作说明,目前大部分项目都采用IO多路复用(同步非阻塞)的模式进行(该模式下又分成了上述3种线程处理模型)。

下一篇将会针对IO多路复用下的三种线程模型,介绍下Selector,以及利用Selector来写一下具体的实现代码。

Java NIO学习与记录(六): NIO线程模型的更多相关文章

  1. Java NIO学习与记录(八): Reactor两种多线程模型的实现

    Reactor两种多线程模型的实现 注:本篇文章例子基于上一篇进行:Java NIO学习与记录(七): Reactor单线程模型的实现 紧接着上篇Reactor单线程模型的例子来,假设Handler的 ...

  2. Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  3. Java NIO学习系列四:NIO和IO对比

    前面的一些文章中我总结了一些Java IO和NIO相关的主要知识点,也是管中窥豹,IO类库已经功能很强大了,但是Java 为什么又要引入NIO,这是我一直不是很清楚的?前面也只是简单提及了一下:因为性 ...

  4. Java NIO学习系列五:I/O模型

    前面总结了很多IO.NIO相关的基础知识点,还总结了IO和NIO之间的区别及各自适用场景,本文会从另一个视角来学习一下IO,即IO模型.什么是IO模型?对于不同人.在不同场景下给出的答案是不同的,所以 ...

  5. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  6. Lucene.net(4.8.0) 学习问题记录六:Lucene 的索引系统和搜索过程分析

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

  7. Android(java)学习笔记211:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  8. Java并发学习(一):进程和线程

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 俗话说得好"一人 ...

  9. Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量

    线程创建与终止 线程创建 Thread类与 Runnable 接口的关系 public interface Runnable {         public abstract void run(); ...

随机推荐

  1. windows聚焦图片文件重命名bash脚本

    win10聚焦路径为: %localappdata%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalStat ...

  2. ModelSim 修改测量时间显示的单位

    经常有网友问,ModelSim仿真时,测量两个点之间的时间,想显示合适的单位怎么设置,例如下图显示的两个测量光标间的时间,是以频率为单位显示的,当希望设置为以时间显示,例如ns或者ms的时候怎么办呢? ...

  3. handsontable-developer guide-setting options,callback

    1.cell数组 cell: [ {row: 0, col: 0, readOnly: true} ] 2.cells函数 cells: function(row, col, prop){ var c ...

  4. [label][Fireworks][转载] Web Slices - Fireworks CS5

    Web Slices – Fireworks CS5 http://bestwebdesignz.com/tips/fireworks/web-slices-fireworks-cs5/ Need a ...

  5. Github的注册经历

    姓名 韦军 学号 1413042023 班级 网络141 兴趣爱好 读书 上网 在注册Github时,先去网上下载了一个Github的app,打开一看全是英文,还是看懂了一些,点击开始注册,在注册时还 ...

  6. DMV--sys.dm_os_ring_buffers

    DMV 'sys.dm_os_ring_buffers' 可以用来诊断数据库连接和数据库内存方面的问题,但MSDN上找不到相应的介绍,网上找到以下相关资料: 1>sys.dm_os_ring_b ...

  7. 疑难杂症--SQL SERVER 18056的错误

    朋友遇到一个很棘手的问题,查看服务器日志,报以下错误: ::,spid296,未知,错误: ,严重性: ,状态: . ::,spid495,未知, The client was unable < ...

  8. solr特点九:word(分词)

    在Solr中配置中文分词IKAnalyzer 1.在配置文件schema.xml(位置{SOLR_HOME}/config/下),配置信息如下: <!-- IKAnalyzer 中文分词--&g ...

  9. .net后台转json数据

    List<PostInfo> list = new List<PostInfo>();PostInfo postinfo = new PostInfo();list.Add(p ...

  10. SQL Server Job

    1. SQL Server Job创建:(SQL Server 代理 - 作业)鼠标右键.新建作业. 2.[常规]选项:定义作业名称.和说明信息. 3:[步骤]选项:新建步骤 4:定义步骤名称.设置对 ...