转载请注明出处:jiq•钦's technical Blog - 季义钦

引言

BIO和NIO是两种不同的网络通信模型,现现在NIO已经大量应用在Jetty、ZooKeeper、Netty等开源框架中。

一个面向流、一个面向缓冲区

一个是堵塞式的、一个非堵塞

一个没有io多路复用器、一个有

以下通过一个样例解释两者差别:

假设当前服务端程序须要同一时候从与多个client建立的连接读取数据。

使用BIO

假设採用堵塞式IO。单线程情况下。处理者线程可能堵塞在当中一个套接字的read上,导致还有一个套接字即使准备好了数据也无法处理。这个时候解决办法就是针对每个套接字。都新建一个线程处理其数据读取。

所以说,在BIO工作模式下,服务端程序要想同一时候处理多个套接字的数据读取,在等待接收连接请求的主线程之外,还要为每个建立好的连接分配一个新的线程进行处理。

使用NIO

轮询方式

假设将套接字读操作换成非堵塞的,那么仅仅须要一个线程就能够同一时候处理套接字,每次检查一个套接字。有数据则读取,没有则检查下一个。由于是非堵塞的。所以运行read操作时若没有数据准备好则马上返回。不会发生堵塞。

 

I/O多路复用

这样的轮询的方式缺点是浪费CPU资源。大部分时间可能都是无数据可读的,不必仍不间断的重复运行read操作,I/O多路复用(IOmultiplexing)是一种更好的方法。调用select函数时。其内部会维护一张监听的套接字的列表,其会一直堵塞直到当中某一个套接字有数据准备好才返回。并告诉是哪个套接字可读,这时再调用该套接字的read函数效率更高。

所以基本能够觉得 “NIO = I/O多路复用 + 非堵塞式I/O”,大部分情况下是单线程。但也有超过一个线程实现NIO的情况

NIO三种模型

上面所讲到的仅仅须要一个线程就能够同一时候处理多个套接字,这仅仅是当中的一种单线程模型,是一种较为极端的情况。NIO主要包括三种线程模型:

1) Reactor单线程模型

2) Reactor多线程模型

3)主从Reactor多线程模型

Reactor单线程模型:

单个线程完毕全部事情包括接收client的TCP连接请求,读取和写入套接字数据等。

对于一些小容量应用场景。能够使用单线程模型。可是对于高负载、大并发的应用却不合适。主要原因例如以下:

1) 一个NIO线程同一时候处理成百上千的链路,性能上无法支撑,即便NIO线程的CPU负荷达到100%,也无法满足海量消息的编码、解码、读取和发送;

2) 当NIO线程负载过重之后。处理速度将变慢,这会导致大量client连接超时,超时之后往往会进行重发。这更加重了NIO线程的负载,终于会导致大量消息积压和处理超时,NIO线程会成为系统的性能瓶颈;

3) 可靠性问题:一旦NIO线程意外跑飞,或者进入死循环,会导致整个系统通信模块不可用。不能接收和处理外部消息,造成节点故障。

为了解决这些问题。演进出了Reactor多线程模型。

Reactor多线程模型:

Rector多线程模型与单线程模型最大的差别就是有一组NIO线程处理真实的IO操作。

Reactor多线程模型的特点:

1) 有专门一个NIO线程-Acceptor线程用于监听服务端,接收client的TCP连接请求;

2) 网络IO操作-读、写等由一个NIO线程池负责,线程池能够採用标准的JDK线程池实现。它包括一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送;

3) 1个NIO线程能够同一时候处理N条链路。可是1个链路仅仅相应1个NIO线程,防止发生并发操作问题。

在绝大多数场景下,Reactor多线程模型都能够满足性能需求;可是,在极特殊应用场景中。一个NIO线程负责监听和处理全部的client连接可能会存在性能问题

比如百万client并发连接,或者服务端须要对client的握手消息进行安全认证,认证本身很损耗性能。在这类场景下,单独一个Acceptor线程可能会存在性能不足问题,为了解决性能问题。产生了第三种Reactor线程模型-主从Reactor多线程模型。

即从单线程中由一个线程即监听连接事件、读写事件、由完毕数据读写,拆分为由一个线程专门监听各种事件。再由专门的线程池负责处理真正的IO数据读写。

主从Reactor多线程模型

主从Reactor线程模型与Reactor多线程模型的最大差别就是有一组NIO线程处理连接、读写事件。

主从Reactor线程模型的特点是:服务端用于接收client连接的不再是个1个单独的NIO线程。而是一个独立的NIO线程池。Acceptor接收到clientTCP连接请求处理完毕后(可能包括接入认证等),将新创建的SocketChannel注冊到IO线程池(sub reactor线程池)的某个IO线程上,由它负责SocketChannel的读写和编解码工作。

Acceptor线程池仅仅仅仅用于client的登陆、握手和安全认证,一旦链路建立成功,就将链路注冊到后端subReactor线程池的IO线程上,由IO线程负责兴许的IO操作。

即从多线程模型中由一个线程来监听连接事件和数据读写事件,拆分为一个线程监听连接事件,线程池的多个线程监听已经建立连接的套接字的数据读写事件,另外和多线程模型一样有专门的线程池处理真正的IO操作。

各自适用场景

NIO适用场景

server须要支持超大量长时间连接。比方10000个连接以上,而且每个client并不会频繁地发送太多数据。比如总公司的一个中心server须要收集全国便利店各个收银机的交易信息。仅仅须要少量线程按需处理维护的大量长期连接。

Jetty、Mina、Netty、ZooKeeper等都是基于NIO方式实现。

BIO适用场景

适用于连接数目比較小。而且一次发送大量数据的场景,这样的方式对server资源要求比較高,并发局限于应用中。

Java IO:BIO和NIO差别及各自应用场景的更多相关文章

  1. java IO(BIO)、NIO、AIO

    IO 服务端ServerSocket 客户端Socket 缺点每次客户端建立连接都会另外启一个线程处理.读取和发送数据都是阻塞式的. 如果1000个客户端建立连接将会产生1000个线程 Server端 ...

  2. Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!

    本文原题“从实践角度重新理解BIO和NIO”,原文由Object分享,为了更好的内容表现力,收录时有改动. 1.引言 这段时间自己在看一些Java中BIO和NIO之类的东西,也看了很多博客,发现各种关 ...

  3. Java中BIO,NIO,AIO的理解

    在高性能的I/O体系设计中,有几个概念常常会使我们感到迷惑不解.具体如下: 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步非阻塞? 7  ...

  4. Java的BIO,NIO,AIO

    Java中的IO操作可谓常见.在Java的IO体系中,常有些名词容易让人困惑不解.为此,先通俗地介绍下这些名词. 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同 ...

  5. Java中BIO和NIO

    同步/异步.阻塞/非阻塞概念 同步异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 同步:在发出一个 ...

  6. 【Java】 BIO与NIO以及AIO分析

    一.BIO与NIO以及AIO的概念 BIO是同步阻塞式的IO NIO是同步非阻塞的IO (NIO1.0,JDK1.4) AIO是非同步非阻塞的IO(NIO2.0,JDK1.7) 二.BIO简单分析 1 ...

  7. java的bio和nio写入及读取txt文件

    一.bio的写入及读取 1.采用bio之BufferedWriter 写入文件 public static void main(String[] args) throws IOException { ...

  8. Java中BIO、NIO、AIO的区别和应用场景

    学习IO,首先要明白四个东西. 1.同步            java自己去处理io. 2.异步          java将io交给操作系统去处理,告诉缓存区大小,处理完成回调. 3.阻塞     ...

  9. java面试题之BIO、NIO、AIO的应用场景

    定义: 1.BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时,服务器就启动一个线程来处理,如果这个连接不处理任何事情会造成不必要的线程开销,可以通过线程池机制改善. 2.NI ...

随机推荐

  1. Java 内存释放

     问题一什么叫垃圾回收机制 垃圾回收是一种动态存储管理技术它自动地释放不再被程序引用的对象按照特定的垃圾收集算法来实现资源自动回收的功能.当一个对象不再被引用的时候内存回收它占领的空间 ...

  2. java 字符串,字符数组,list间的转化

    1.关于java.lang.string.split xxx.split()方法可以将一个字符串分割为子字符串,然后将结果作为字符串数组返回. 2.字符串转字符数组 String str =" ...

  3. eclipse Reference 功能之——项目之间的引用

    i'm sorry, i forgot this article where i found. that it is referenced. 以前也研究过Eclipse里Web Project引用Ja ...

  4. Mac 在启动eclipse时 Failed to load JavaHL Library解决方法

    在Mac 10.9.1系统里, 在Eclipse中安装svn的插件,出现如下提示 方法一: 1.根据提示进入链接 http://subclipse.tigris.org/wiki/JavaHL 2. ...

  5. 偏执却管用的10条Java编程技巧

    本文由 ImportNew - LynnShaw 翻译自 javacodegeeks.欢迎加入翻译小组.转载请见文末要求. 经过一段时间的编码(咦,我已经经历了将近20年的编程生涯,快乐的日子总是过得 ...

  6. 如何设置eclipse不同的workspace共享配置

    在很多的项目中,每个项目使用一个workspace,结果每新建一个workspace重新配置一下,但是配置的东西都是一样的,烦死了,有什么好办法可以共享一下配置呢? 总结一下,复制工作空间配置步骤如下 ...

  7. easyui input设置为disabled提交后获取不到属性值

    在做网站管理后台的用户修改功能时,由于当前用户修改个人信息时规定用户名不能修改,故使用了input标签的disabled属性,但是在提交数据后却发现用户名显示为空了.后 来一查才知道input设置为d ...

  8. Android导航抽屉-Navigation Drawer

    Google今年七月份的时候更新了他们的Google+应用,采用了新的导航方式并抛弃了navigationdrawer.一时之间,又引发了一系列关于NavigationDrawer利弊的讨论,不过对于 ...

  9. SQL Server 视图索引

    在视图上创建索引的另一个好处是:查询优化器开始在查询中使用视图索引,而不是直接在 FROM 子句中命令视图.这样一来,可从索引视图检索数据而无需重新编码,由此带来的高效率也使现有查询获益.在视图上创建 ...

  10. .NET MVC自定义错误处理页面的方法

    在ASP.NET MVC中,我们可以使用HandleErrorAttribute特性来具体指定如何处理Action抛出的异常.只要某个Action设置了HandleErrorAttribute特性,那 ...