Java的中BIO、NIO、AIO-2

Java的中BIO、NIO、AIO-2

java

举个栗子

接上一篇接着说,C/S模式、Reactor模式、Proactor模式是服务器处理IO常用的处理模型,这一篇就来解释一下这几种模式:

以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐。就像一个网站会有很多的请求,要求服务器做一些事情。处理这些就餐事件的就需要我们的服务人员了。

在多线程处理的方式会是这样的:

一个人来就餐,一个服务员去服务,然后客人会看菜单,点菜。 服务员将菜单给后厨。

二个人来就餐,二个服务员去服务……

五个人来就餐,五个服务员去服务……

这个就是多线程的处理方式,一个事件到来,就会有一个线程服务。很显然这种方式在人少的情况下会有很好的用户体验,每个客人都感觉自己是VIP,专人服务的。如果餐厅一直这样同一时间最多来5个客人,这家餐厅是可以很好的服务下去的。(这样就很熟悉了,这既是最简单来一个Socket连接,就创建一个线程。)

但是越来越多的人对这家餐厅满意,客源又多了,同时来吃饭的人到了20人,老板高兴不起来了,再请服务员吧,占地方不说,还要开工钱,再请人就攒不到钱了。怎么办呢?老板想了想,10个服务员对付20个客人也是能对付过来的,服务员勤快点就好了,伺候完一个客人马上伺候另外一个,还是来得及的。综合考虑了一下,老板决定就使用10个服务人员的线程池啦。(创建固定数量的线程池,建一个任务队列,使用多线程的方式对任务进行处理)

但是如果人数太多,那么10个人的服务员根本忙不过来,同样,没有人的时候,10个人的服务员在闲等着又造成了很大的资源浪费。

老板后来发现,客人点菜比较慢,大部服务员都在等着客人点菜,其实干的活不是太多。老板能当老板当然有点不一样的地方,终于发现了一个新的方法,那就是:当客人点菜的时候,服务员就可以去招呼其他客人了,等客人点好了菜,直接招呼一声“服务员”,马上就有个服务员过去服务。老板决定改变经营模式。(这就是Reactor模式!!)

后面老板做出了名声,有钱了,萌生出一个新的想法,做外卖。用户打电话告诉接单员他的订单,然后接单员把订单发给餐饮部门,接单员可以继续工作接单,等餐饮部门把订单做好的时候,告诉接单员订单完成来取饭,接单员根据订单信息把饭菜交给外卖小哥送出去。(这就是Proactor模式!!)

前面是举例子说明这几种模式,可能这样理解起来很懵,下面就每种模式详细的说明一下:

1. BIO中的C/S编程模型

网络编程的基本模型是C/S模型,也就是两个进程间的通信。服务端提供IP和监听端口,客户端通过向服务器端的端口发起连接请求,通过三次握手如果连接成功,双方就能进行套接字通信了,这就是TCP连接,当然只是废话。

在传统的同步阻塞开发模型中,服务器ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接,连接成功之后,双方通过输入输出流进行同步阻塞式通信。采用BIO通信模型的服务器端,通常有一个独立的线程负责监听客户端的连接,它接收到客户端的请求连接之后会为每一个客户端创建一个线程进行链路的连接,连接结束之后销毁线程。看下图示例:

BIO通信模型

该模型最大的缺点是缺乏弹性伸缩能力,服务端线程个数和客户端的并发访问数是1:1的关系,当客户端的数目过多的时候,服务器可能承受不住,频繁的创建、销毁线程也很消耗系统资源。

2.伪装异步编程模型

一对一的TCP连接服务太浪费资源,为了改进这一点,可以使用线程池来管理这些线程,为什么是伪异步呢,因为其实对于线程池中线程而言还是一对一的服务这点并没有什么改变。使用线程池知识能够对资源实现有效的管控和约束。

伪异步IO编程模型

当线程池中的数目有限的时候,如果有大量的并发请求,超过最大线程使用数目之后只能进行等待,知道线程池中有空闲的线程可以使用,同时线程对socket的处理模型还是采用阻塞的方式进行处理。

3.Reactor模式

Reactor模式

Reactor模式用于同步IO。开发者开始的时候要把自己感兴趣的时间注册到事件分离器,并提供相应的处理函数。时间分离器等待某个事件可应用或者某个操作的状态发生改变(比如文件描述符可读写、或者是Socket可读写),事件分离器会把这个事件传给时间注册的事件处理器或者回调函数,由其来完成实际的读写操作。下面以读操作为例来说明一下Reactor的具体步骤:

  1. 程序注册读就绪事件和相关联的处理器
  2. 事件分离器等待事件的发生
  3. 当发生读就绪事件的时候,事件分离器调用第一步注册的事件处理器
  4. 事件处理器执行实际的读取操作。如果需要,它可以再次的宣称对这个读就绪事件感兴趣,重复上面的步骤。

觉得这样说明起来其实很虚,第三篇将会演示具体的代码。

4.Proactor模式

Proactor模式

Proactor模式用于异步IO。它其实和reactor模式很相似,也是需要先注册事件到时间分离器,并提供相应的处理函数。但是这个事件不是就绪事件,而是直接发起一个异步的读写操作(请求)事件,但是实际的工作有操作系统完成。在发起事件的时候,需要的提供的参数包括用于存放数据的缓存区,以及这个请求完成之后的回调函数等信息。事件分离器等待这个事件的完成,然后转发完成后的事件给相应的处理函数或者回调等。

下面来以读事件为例说明一下该模式的具体步骤:

  1. 应用程序初始化一个异步读取操作,然后注册相应的事件处理器,此时事件处理器不关注读取就绪事件,而是关注读取完成事件,这是区别于Reactor的关键。
  2. 事件分离器等待读取操作完成事件
  3. 在事件分离器等待读取操作完成的时候,操作系统调用内核线程完成读取操作,并将读取的内容放入用户传递过来的缓存区中。这也是区别于Reactor的一点,Proactor中,应用程序需要传递缓存区。
  4. 事件分离器捕获到读取完成事件后,激活应用程序注册的事件处理器,事件处理器直接从缓存区读取数据,而不需要进行实际的读取操作。如果有需要还可以继续注册事件到事件处理器,重复上面的步骤。

简单总结一下,Reactor和Proactor的异同:

  • 他们相同的地方框架大致相同,程序都需要注册相应的时间到事件分离器,事件分离器根据状态的变化来告知相应的事件处理器。都是事件驱动型的IO通信复用模型。
  • 他们不同的地方,关注的事件不一样,Reactor模式关注的是时间的就绪状态,Proactor模式关注的是事件的完成状态。Reactor模式的程序自己读取或者写入数据,而Proactor模式中,应用程序不需要进行实际的读写过程,它只需要从缓存区读取或者写入即可,操作系统会读取缓存区或者写入缓存区到真正的IO设备(Proactor需要操作系统提供完善的异步操作的API接口)。

所以总的来说,同步和异步是相对于应用和内核的交互方式而言的,同步 需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式而已。

参考资料

原文地址:https://www.cnblogs.com/chailinbo/p/9226274.html

时间: 2024-08-29 13:56:27

Java的中BIO、NIO、AIO-2的相关文章

JAVA 中BIO,NIO,AIO的理解

JAVA 中BIO,NIO,AIO的理解 博客分类: 网络编程 [转自]http://qindongliang.iteye.com/blog/2018539 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 什么是异步阻塞? 8 什么是异步非阻塞? 散仙不才,在查了一部分资料后,愿试着以通俗易懂的方式解释下这几个名词.如有不足之处,还

java并发之bio nio aio

最近在进行tomcat优化,发现tomcat connector并发支持bio nio apr,发现想要理解tomcat并发离不开java io的理解.所有本文先探讨java对io的支持.java的io需要操作系统的支持,本文描述linux系统对io的支持,windows系统因为java生成环境使用少不再论述. 一.linux操作系统io的支持 1.同步阻塞 I/O(bio) 2.同步非阻塞I/O(nio) 3.异步非阻塞 I/O(aio) 二.java 包对io的支持 原文地址:https:/

Java中BIO,NIO,AIO的理解

在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 什么是异步阻塞? 8 什么是异步非阻塞? 先来举个实例生活中的例子: 如果你想吃一份宫保鸡丁盖饭: 同步阻塞:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊! 同步非阻塞:在饭馆点完餐,就去遛狗了.不过溜一会儿,就回饭馆喊一声:好了没啊! 异步阻塞:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自

BIO NIO AIO区别

JAVA 中BIO,NIO,AIO的理解 在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下:  序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7 什么是异步阻塞? 8 什么是异步非阻塞? 散仙不才,在查了一部分资料后,愿试着以通俗易懂的方式解释下这几个名词.如有不足之处,还望告知. 在弄清楚上面的几个问题之前,我们首先得明白什么是同步,异步,阻塞,非阻塞,只有这几个单个概念理解清楚了,

JAVA中的BIO,NIO,AIO

在了解BIO,NIO,AIO之前先了解一下IO的几个概念: 1.同步 用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪, 例如自己亲自出马持银行卡到银行取钱 2.异步 用户触发IO操作以后,可以干别的事,IO操作完成以后再通知当前线程,例如让小弟去银行帮你取钱,你可以干别的事 3.阻塞 当试图进读写文件的时候,发现不可读取或没东西读,则进入等待状态知道可读,ATM排队取钱 4.非阻塞 用户进程访问数据时,会马上返回一个状态值(可读不可读),比如在银行柜台办理业务,先取个号,然后坐在椅子

初理解Java中的BIO,NIO,AIO

初识: java 中的 BIO.NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装.程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码.只需要使用Java的API就可以了. 在讲 BIO,NIO,AIO 之前先来回顾一下这样几个概念:同步与异步,阻塞与非阻塞. 同步与异步: 同步: 同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回. 异步: 异步就是发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但

也谈BIO | NIO | AIO (Java版--转)

关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一个解释: BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个层面: 编程语言 实现原理 底层基础 从编程语言层面 BIO | NIO | AIO 以Java的角度,理解,linux c里也有AIO的概念(库),这些概念不知道什么原因被炒火起来,这里只从Java角度入手. BIO,同步阻塞式IO,简单理解:一个连接一个线程 NIO,同步非阻塞IO,简单理解:一

Java的中BIO、NIO、AIO-1

Java的中BIO.NIO.AIO-1 java 最近在项目中用到TCP通信来完成命令和运行结果的交互,用的是典型的TCP通信中的C/S架构,原因很简单:在业务需求低的环境下,这种架构简单.稳定还容易写.但是在实际部署的情况下,一直出现读不到数据的空指针异常,按说BIO模式开发的应该阻塞直到有数据读取,没有找到原因就变通写了一个消息队列,使用定时器每1s从定时器中拿数据,解决了这个问题.但是想想这种同步阻塞的形式,就想了解一下其他的模式:NIO.AIO.好了,啰嗦了好多,进入正题: IO操作的基

一站式学习Java网络编程 全面理解BIO/NIO/AIO

第1章 [开宗明义]网络编程三剑客BIO.NIO.AIO网络编程是RPC的奠基,RPC编程贯穿了程序员生涯的始终.本章首先分析为什么要学网络编,本课为谁设计,然后介绍课程内容主线脉络,让大家清晰知道本课程并非光说不练的假把式,而是处处有实战,实战项目步步优化,最后通过综合项目巩固所学.... 第2章 网络层的解析与协议本章首先对网络中涉及的网络链路层的解析进行讲解,进一步引出网络基本协议知识.使学员了解分层思想,对三种协议的定位及作用有所了解. 第3章 解读java.io专业术语也可以变得生动精