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(); ...
随机推荐
- mysql中timestamp简单用法
该时间字段有比较特殊的地方,显示内容datetime字段一样.当取值为null或者不赋值时,显示当前系统时间,然后在其他地区读取的时候会根据当地的时间转换成当地的系统时间.
- 协程库st(state threads library)原理解析
协程库state threads library(以下简称st)是一个基于setjmp/longjmp实现的C语言版用户线程库或协程库(user level thread). 这里有一个基本的协程例子 ...
- NLTK和Stanford NLP两个工具的安装配置
这里安装的是两个自然语言处理工具,NLTK和Stanford NLP. 声明:笔者操作系统是Windows10,理论上Windows都可以: 版本号:NLTK 3.2 Stanford NLP 3.6 ...
- windows cmake安装
https://blog.csdn.net/u013832707/article/details/53127710
- Caffe 议事(二):从零开始搭建 ResNet 之 网络的搭建(上)
3.搭建网络: 搭建网络之前,要确保之前编译 caffe 时已经 make pycaffe 了. 步骤1:导入 Caffe 我们首先在 ResNet 文件夹中建立一个 mydemo.py 的文件,本参 ...
- CentOS 7 装好系统一些优化
1.禁用SELINUX vi /etc/sysconfig/selinux 设置为disabled 2.同步时间*/20 * * * * /usr/sbin/ntpdate pool.ntp.org ...
- SDWebImage从缓存中获取图片
if ([[SDImageCache sharedImageCache] imageFromKey:sort.imageUrl]) { [cell.photoImageView s ...
- MySQL—练习
前面学习了MySQL的语句的基本用法,这里就开始做一些MySQL练习,这套题目一共45题,属于比较简单的,初学先试着做这个. 参考链接:https://www.cnblogs.com/SJP666/p ...
- [C#]获取当前程序运行路径的方法集合(转)
//获取当前进程的完整路径,包含文件名(进程名).string str = this.GetType().Assembly.Location;result: X:\xxx\xxx\xxx.exe (. ...
- [转载]WCF系列_分布式事务(下)
浏览到chnking的WCF的分布式事务处理不错,转载过来分享一下. 1. WCF分布式事务例子这里也用转账的例子说事.用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B ...