Java NIO学习与记录(六): NIO线程模型
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线程模型的更多相关文章
- Java NIO学习与记录(八): Reactor两种多线程模型的实现
Reactor两种多线程模型的实现 注:本篇文章例子基于上一篇进行:Java NIO学习与记录(七): Reactor单线程模型的实现 紧接着上篇Reactor单线程模型的例子来,假设Handler的 ...
- Java NIO 学习笔记(六)----异步文件通道 AsynchronousFileChannel
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Java NIO学习系列四:NIO和IO对比
前面的一些文章中我总结了一些Java IO和NIO相关的主要知识点,也是管中窥豹,IO类库已经功能很强大了,但是Java 为什么又要引入NIO,这是我一直不是很清楚的?前面也只是简单提及了一下:因为性 ...
- Java NIO学习系列五:I/O模型
前面总结了很多IO.NIO相关的基础知识点,还总结了IO和NIO之间的区别及各自适用场景,本文会从另一个视角来学习一下IO,即IO模型.什么是IO模型?对于不同人.在不同场景下给出的答案是不同的,所以 ...
- Android(java)学习笔记267:Android线程池形态
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- Lucene.net(4.8.0) 学习问题记录六:Lucene 的索引系统和搜索过程分析
前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...
- Android(java)学习笔记211:Android线程池形态
1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...
- Java并发学习(一):进程和线程
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 俗话说得好"一人 ...
- Java基础学习总结(88)——线程创建与终止、互斥、通信、本地变量
线程创建与终止 线程创建 Thread类与 Runnable 接口的关系 public interface Runnable { public abstract void run(); ...
随机推荐
- Sketch插件新利器——使用Mockplus DS制作设计规范
Sketch,作为一款专为图标和界面设计而打造的优质矢量绘图工具,也是设计师们制作和完善公司企业内部设计规范系统不可或缺的设计工具. 然而,逐个导出和上传Sketch编辑优化的设计系统资源费时而费力. ...
- DIV+CSS布局时, DIV的高度和宽度特性
这个没有特别的做要求,你要根据你自己的页面整体布局来设置,还有根据div的特性来设置,div默认情况是宽度最大化(100%).高度最小化,高度随着内容自动伸展: 一般情况做网页的话,大部分都是固定了总 ...
- 08 Translating RNA into Protein
Problem The 20 commonly occurring amino acids are abbreviated by using 20 letters from the English a ...
- AngularJS-$scope类
一.$scope的作用 用来在controller和view中进行数据.事件的传递 二.$scope和$rootscope的区别 1.$rootscope根作用域 2.$rootscope可以实现多个 ...
- windows7文件夹怎样默认图片大图显示?
先打开一个含有图片的文件夹,在文件夹空白处右键选择属性,打开自定义选项卡. 确定自定义选项卡 显示的是:“优化此文件夹:图片”. 然后,选择:组织--文件夹和搜索选项--查看--文件夹视图,应用到文件 ...
- MFC中的一般经验之谈2
MFC一般类成员m_iAge,命名原则,且MFC中类定义以C开头原则,这些原则便于理解以及增强代码的可读性.MFC是一个用窗口作为用户交互的方式,一般框架类.视图类.以及窗口上的控件都是继承CWnd类 ...
- Jmeter-Ant 生成测试报告
一.安装jmeter 配置环境变量 JMETER_HOME D:\SProgram\jmeter CLASSPATH %JMETER_HOME\lib\ext\ApacheJMeter_core.ja ...
- Java反射API研究(3)——java.lang.Class<T>
对于反射来说,Class是核心,任何反射的对象都需要通过Class来获得. Class 类的实例表示正在运行的 Java 应用程序中的类和接口.枚举是一种类,注释是一种接口.每个数组属于被映射为 Cl ...
- [LeetCode 题解]: Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1 ...
- solr-DIH:dataimport增量全量创建索引
索引创建完毕,就要考虑怎么定时的去重建, 除了写solrj,可以定时调用下面两条url进行增量或者全量创建索引 全量:http://ip:port/webapp_name/core_name/da ...