原文:http://huangxx.iteye.com/blog/193742

  1. 通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞与非阻塞。所谓阻塞方式的意思是指, 当试图对该文件描述符进行读写时, 如果当时没有东西可读,或者暂时不可写, 程序就进入等待状态, 直到有东西可读或者可写为止。而对于非阻塞状态, 如果没有东西可读, 或者不可写, 读写函数马上返回, 而不会等待。
  2. 在前面的章节中提到的Tcp通信的例子中,就是采用的阻塞式的工作方式:当接收tcp数据时,如果远端没有数据可以读,则会一直阻塞到读到需要的数据为止。这种方式的传输和传统的被动方法的调用类似,非常直观,并且简单有效,但是同样也存在一个效率问题,如果你是开发一个面对着数千个连接的服务器程序,对每一个客户端都采用阻塞的方式通信,如果存在某个非常耗时的读写操作时,其它的客户端通信将无法响应,效率非常低下。
  3. 一种常用做法是:每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况。
  4. 另一种较高效的做法是:服务器端保存一个Socket连接列表,然后对这个列表进行轮询,如果发现某个Socket端口上有数据可读时(读就绪),则调用该socket连接的相应读操作;如果发现某个Socket端口上有数据可写时(写就绪),则调用该socket连接的相应写操作;如果某个端口的Socket连接已经中断,则调用相应的析构方法关闭该端口。这样能充分利用服务器资源,效率得到了很大提高。
  5. 系统I/O方式可分为阻塞,非阻塞同步和非阻塞异步三类,三种方式中,非阻塞异步模式的扩展性和性能最好。主要是讲了两种IO多路复用模式:Reactor和Proactor,并对它们进行了比较。
  6. 两种I/O多路复用模式:Reactor和Proactor
  7. 一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器对象可将来自事件源的I/O事件分离出来,并分发到对应的read/write事件处理器(Event Handler)。开发人员预先注册需要处理的事件及其事件处理器(或回调函数);事件分离器负责将请求事件传递给事件处理器。两个与事件分离器有关的模式是Reactor和Proactor。Reactor模式采用同步IO,而Proactor采用异步IO。
  8. 在Reactor中,事件分离器负责等待文件描述符或socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。
  9. 而在Proactor模式中,处理器--或者兼任处理器的事件分离器,只负责发起异步读写操作。IO操作本身由操作系统来完成。传递给操作系统的参数需要包括用户定义的数据缓冲区地址和数据大小,操作系统才能从中得到写出操作所需数据,或写入从socket读到的数据。事件分离器捕获IO操作完成事件,然后将事件传递给对应处理器。比如,在windows上,处理器发起一个异步IO操作,再由事件分离器等待IOCompletion事件。典型的异步模式实现,都建立在操作系统支持异步API的基础之上,我们将这种实现称为“系统级”异步或“真”异步,因为应用程序完全依赖操作系统执行真正的IO工作。
  10. 举个例子,将有助于理解Reactor与Proactor二者的差异,以读操作为例(类操作类似)。
  11. 在Reactor中实现读:
  12. - 注册读就绪事件和相应的事件处理器
  13. - 事件分离器等待事件
  14. - 事件到来,激活分离器,分离器调用事件对应的处理器。
  15. - 事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。
  16. 与如下Proactor(真异步)中的读过程比较:
  17. - 处理器发起异步读操作(注意:操作系统必须支持异步IO)。在这种情况下,处理器无视IO就绪事件,它关注的是完成事件。
  18. - 事件分离器等待操作完成事件
  19. - 在分离器等待过程中,操作系统利用并行的内核线程执行实际的读操作,并将结果数据存入用户自定义缓冲区,最后通知事件分离器读操作完成。
  20. - 事件分离器呼唤处理器。
  21. - 事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分离器。
  22. Java NIO非堵塞应用通常适用用在I/O读写等方面,我们知道,系统运行的性能瓶颈通常在I/O读写,包括对端口和文件的操作上,过去,在打开一个I/O通道后,read()将一直等待在端口一边读取字节内容,如果没有内容进来,read()也是傻傻的等,这会影响我们程序继续做其他事情,那么改进做法就是开设线程,让线程去等待,但是这样做也是相当耗费资源的。
  23. Java NIO非堵塞技术实际是采取Reactor模式,或者说是Observer模式为我们监察I/O端口,如果有内容进来,会自动通知我们,这样,我们就不必开启多个线程死等,从外界看,实现了流畅的I/O读写,不堵塞了。
  24. Java NIO出现不只是一个技术性能的提高,你会发现网络上到处在介绍它,因为它具有里程碑意义,从JDK1.4开始,Java开始提高性能相关的功能,从而使得Java在底层或者并行分布式计算等操作上已经可以和C或Perl等语言并驾齐驱。
  25. NIO主要原理和适用。
  26. NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有事件发生时,他会通知我们,传回一组SelectionKey,我们读取这些Key,就会获得我们刚刚注册过的socketchannel,然后,我们从这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些数据。
  27. Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮询(目前就这一个算法),一旦轮询到一个channel有所注册的事情发生,比如数据来了,他就会站起来报告,交出一把钥匙,让我们通过这把钥匙来读取这个channel的内容。

以下来自:http://rhythm-zju.blog.163.com/blog/static/31004200801504351529/

首先让我们对异步 I/O 做一些基本的了解。异步 I/O 模型大体上可以分为两种,反应式( Reactive )模型和前摄式( Proactive )模型:

传统的 select / epoll / kqueue 模型,以及 Java NIO 模型,都是典型的反应式模型,即应用代码对 I/O 描述符进行注册,然后等待 I/O 事件。当某个或某些 I/O 描述符所对应的 I/O 设备上产生 I/O 事件(可读、可写、异常等)时,系统将发出通知,于是应用便有机会进行 I/O 操作并避免阻塞。由于在反应式模型中应用代码需要根据相应的事件类型采取不同的动作,最常见的结构便是嵌套的 if {...} else {...}  或 switch ,并常常需要结合状态机来完成复杂的逻辑。

前摄式模型则恰恰相反。在前摄式模型中,应用代码主动地投递异步操作而不管 I/O 设备当前是否可读或可写。投递的异步 I/O 操作被系统接管,应用代码也并不阻塞在该操作上,而是指定一个回调函数并继续自己的应用逻辑。当该异步操作完成时,系统将发起通知并调用应用代码指定的回调函数。在前摄式模型中,程序逻辑由各个回调函数串联起来:异步操作 A 的回调发起异步操作 B ,B 的回调再发起异步操作 C ,以此往复。Mina 便是一个前摄式的异步 I/O 框架。

前摄式模型相较于反射式模型往往更加难以编程。然而在具有原生异步 I/O 支持的操作系统中(例如支持 IO Completion Port 的 Win32 系统),采用前摄式模型往往可以取得比反应式模型更佳的效率。在没有原生异步 I/O 支持的系统中,也可以使用传统的反应式 API 对前摄式模型予以模拟。在现代的软硬件系统中,使用 epoll 和 kqueue 的前摄式模型实现同样可以轻松解决 C10K 问题。前摄式模型的一个显著优势是在实现复杂逻辑的时候不需要借助于状态机。因为状态机已经隐含在由回调串联起来的异步操作链当中了。如果上述内容难以理解,可以参考Boost.Asio ,这是一个相当优秀的跨平台 C++ 前摄式 I/O 模型实现。

延伸阅读: http://www.artima.com/articles/io_design_patterns.html

C10K:http://www.kegel.com/c10k.html

反应器(Reactor):用于事件多路分离和分派的体系结构模式相关推荐

  1. 【转】第8章 前摄器(Proactor):用于为异步事件多路分离和分派处理器的对象行为模式...

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  2. ACE反应器(Reactor)模式

    1.ACE反应器框架简介 反应器(Reactor):用于事件多路分离和分派的体系结构模式 通常的,对一个文件描述符指定的文件或设备, 有两种工作方式: 阻塞与非阻塞.所谓阻塞方式的意思是指, 当试图对 ...

  3. 模式设计概述:反应器(Reactor)模式

    事件处理模式 在<面向模式的软件体系架构卷2:用于并发和网络化对象模式>中,总结了对于当前比较流行的事件处理模式的四种基本模式,分别是反应器模式.主动器模式.异步完成标记和接收器-连接器模 ...

  4. 【Netty】反应器 Reactor 模式 ( 单反应器 Reactor 单线程 | 单反应器 Reactor 多线程 )

    文章目录 一. 反应器 ( Reactor ) 模式 二. 反应器 ( Reactor ) 模式两大组件 三. 单反应器 ( Reactor ) 单线程 四. 单反应器 ( Reactor ) 单线程 ...

  5. 反应器(Reactor)模式-golang探索

    反应器模式 在以前的博文模式设计概述:反应器(Reactor)模式介绍过相关的概念和流程,当时使用了python但是从结果上来看并没有起到很明显的效果.最近在处理有关proxy的项目中,刚刚好涉及到有 ...

  6. 【Netty】主从反应器 ( Reactor ) 多线程模型

    文章目录 一. 主从 反应器 ( Reactor ) 多线程 模式 二. 主从 反应器 ( Reactor ) 多线程 工作流程 三. 主从 反应器 ( Reactor ) 多线程 优缺点分析 四. ...

  7. QT 触控事件和鼠标事件的分离(问题已解决)

    问题:QT图形视图框架,QGraphicsScene中默认接收触控事件,会将第一个点当作鼠标事件处理. 在开发者开发的时候,可能会有这样的需求,希望自己的触控事件和鼠标事件能够分割开来. 找到的解决方 ...

  8. Win10 权限问题:用于内置管理员账户的管理员批准模式

    需求背景 为了安全考虑微酷将 Win10 系统电脑各盘符安全设置为只保留Administrators和SYSTEM两个用户组可完全访问,然后平时用电脑都是用内置管理员administrator来使用, ...

  9. 把 LiveData 用于事件传递那些坑

    0.前言 如果不是很了解 LiveData 和 Lifecycle 的同学可以先看一下我之前的文章 基于 Android Architecture Components 的 MVVM 浅析.同时安利下 ...

最新文章

  1. NLP专题论文解读:从Chatbot、NER到QA系统...
  2. 预计2024年之前载人登月!NASA授予马斯克贝索斯公司大单
  3. 全志 添加外挂RTC Hym8563
  4. Java编辑环境搭建
  5. OpenCV 文本显示 putText 和 getTextSize
  6. sharelatex 编辑论文
  7. html网页设计课程设计总结,网页制作课程设计报告总结.doc
  8. 简单典型二阶系统_非典型二阶系统的特性
  9. jQuery全屏插件fullPage的基本使用
  10. 腾达ac1200开虚拟服务器,腾达F1200 11AC双频无线路由器的上网设置教程
  11. 创建表 编码_创建没有编码的专业商业网站
  12. 【黄啊码】MySQL入门—5、数据库小技巧:单个列group by就会,多个列呢?
  13. Word2003快速操作技巧及常用快捷键使用
  14. [POI2007]立方体大作战tet
  15. 解决Spyder无法抓取Yahoo!finance财经数据
  16. unity 正六边形网格绘制(精简版)-代码可直接复用
  17. 开发者账号申请流程(公司的),APPID的申请,邓白氏编码的申请
  18. 微信小程序富文本长按复制粘贴
  19. Java猜字小游戏求助
  20. 北京企业科技研究开发机构认定,奖励100万

热门文章

  1. 32 FI配置-财务会计-应收账款和应付账款-定义客户预付款的统驭科目
  2. 一起学习C语言:C语言基本语法(三)
  3. js转义字符 php 反转义6,JS实现HTML标签转义及反转义
  4. opencv计算物体姿态旋转_物体的三维识别与6D位姿估计:PPF系列论文介绍(五)...
  5. OpenCV:分离图像和视频的RGB通道
  6. OpenVINO InferenceEngine之CNNNet、CNNLayer、Blob介绍
  7. ubuntu自带截图工具--方便好用
  8. 【PyTorch】lr_scheduler.StepLR==>调整学习率的方法
  9. 6-3Table API SQL简介
  10. Anatomy of a Flink Program(Flink程序的剖析)