详解BIO与NIO的区别

1、 Reactor and Proactor数据库

IO读写时,多路复用机制都会依赖对一个事件多路分离器,负责把源事件的IO 事件分离出来,分别到相应的read/write事件分离器。涉及到事件分离器的两种模式分别就是 Reactor和Proactor,Reactor是基于同步IO的,Proactor是基于异步IO的。缓存

在Reactor模式中,事件分离者等待某个事件或者可应用或个操做的状态发生(好比文件描述符可读写,或者是socket可读写),事件分离者就把这个事件传给事先注册的事件处理函数或者回调函数,由后者来作实际的读写操做。网络

在Proactor模式中,事件处理者(或者代由事件分离者发起)直接发起一个异步读写操做(至关于请求),而实际的工做是由操做系统来完成的。发起时,须要提供的参数包括用于存放读到数据的缓存区,读的数据大小,或者用于存放外发数据的缓存区,以及这个请求完后的回调函数等信息。事件分离者得知了这个请求,它默默等待这个请求的完成,而后转发完成事件给相应的事件处理者或者回调。举例来讲,在Windows上事件处理者投递了一个异步IO操做(称有 overlapped的技术),事件分离者等IOCompletion事件完成. 这种异步模式的典型实现是基于操做系统底层异步API的,因此咱们可称之为“系统级别”的或者“真正意义上”的异步,由于具体的读写是由操做系统代劳的。app

举个例子,将有助于理解Reactor与Proactor两者的差别,以读操做为例(类操做相似)。异步

在Reactor中实现读:socket

- 注册读就绪事件和相应的事件处理器函数

- 事件分离器等待事件spa

- 事件到来,激活分离器,分离器调用事件对应的处理器。操作系统

- 事件处理器完成实际的读操做,处理读到的数据,注册新的事件,而后返还控制权。线程

与以下Proactor(真异步)中的读过程比较:

- 处理器发起异步读操做(注意:操做系统必须支持异步IO)。在这种状况下,处理器无视IO就绪事件,它关注的是完成事件。

- 事件分离器等待操做完成事件

- 在分离器等待过程当中,操做系统利用并行的内核线程执行实际的读操做,并将结果数据存入用户自定义缓冲区,最后通知事件分离器读操做完成。

- 事件分离器呼唤处理器。

- 事件处理器处理用户自定义缓冲区中的数据,而后启动一个新的异步操做,并将控制权返回事件分离器。

能够看出,两个模式的相同点,都是对某个IO事件的事件通知(即告诉某个模块,这个IO操做能够进行或已经完成)。在结构

上,二者也有相同点:demultiplexor负责提交IO操做(异步)、查询设备是否可操做(同步),而后当条件知足时,就回调handler;

不一样点在于,异步状况下(Proactor),当回调handler时,表示IO操做已经完成;同步状况下(Reactor),回调handler时,表示

IO设备能够进行某个操做(can read or can write),handler这个时候开始提交操做。

2、BIO、NIO、AIO

NIO一般采用Reactor模式,AIO一般采用Proactor模式。AIO简化了程序的编写,stream的读取和写入都有OS来完成,不须要像NIO那样子遍历Selector。Windows基于IOCP实现AIO,Linux只有eppoll模拟实现了AIO。

Java7以前的JDK只支持NIO和BIO,从7开始支持AIO。

4种通讯方式:TCP/IP+BIO, TCP/IP+NIO, UDP/IP+BIO, UDP/IP+NIO。

TCP/IP+BIO、

Socket和ServerSocket实现,ServerSocket实现Server端端口监听,Socket用于创建网络IO链接。

不适用于处理多个请求 1.生成Socket会消耗过多的本地资源。2. Socket链接的创建通常比较慢。

BIO状况下,能支持的链接数有限,通常都采起accept获取Socket之后采用一个thread来处理,one connection one thread。不管链接是否有真正数据请求,都须要独占一个thread。

能够经过设立Socket池来必定程度上解决问题,可是使用池须要注意的问题是:1. 竞争等待比较多。 2. 须要控制好超时时间。

TCP/IP+NIO

使用Channel(SocketChannel和ServerSocketChannel)和Selector。

Server端一般由一个thread来监听connect事件,另外多个thread来监听读写事件。这样作的好处是这些链接只有在真是请求的时候才会建立thread来处理,one request one thread。这种方式在server端须要支持大量链接但这些链接同时发送请求的峰值不会不少的时候十分有效。

UDP/IP+BIO

DatagramSocket和DatagramPacket。DatagramSocket负责监听端口以及读写数据,DatagramPacket做为数据流对象进行传输。

UDP/IP是无链接的,没法进行双向通讯,除非双方都成为UDP Server。

UDP/IP+NIO

经过DatagramChannel和ByteBuffer实现。DatagramChannel负责端口监听及读写。ByteBuffer负责数据流传输。

若是要将消息发送到多台机器,若是为每一个目标机器都创建一个链接的话,会有很大的网络流量压力。这时候可使用基于UDP/IP的Multicast协议传输,Java中能够经过MulticastSocket和DatagramPacket来实现。

Multicast通常多用于多台机器的状态同步,好比JGroups。SRM, URGCP都是Multicast的实现方式。eBay就采用SRM来实现将数据从主数据库同步到各个搜索节点机器。


本文出自 “陈砚羲” 博客,谢绝转载!

相关文章
相关标签/搜索