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

引言

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

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

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

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

下面通过一个例子解释两者区别:

假设当前服务端程序需要同时从与多个客户端建立的连接读取数据。

使用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单线程模型:

单个线程完成所有事情包括接收客户端的TCP连接请求,读取和写入套接字数据等。

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

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

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

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

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

Reactor多线程模型:

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

Reactor多线程模型的特点:

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

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

3) 1个NIO线程可以同时处理N条链路,但是1个链路只对应1个NIO线程,防止发生并发操作问题。

在绝大多数场景下,Reactor多线程模型都可以满足性能需求;但是,在极特殊应用场景中,一个NIO线程负责监听和处理所有的客户端连接可能会存在性能问题。例如百万客户端并发连接,或者服务端需要对客户端的握手消息进行安全认证,认证本身非常损耗性能。在这类场景下,单独一个Acceptor线程可能会存在性能不足问题,为了解决性能问题,产生了第三种Reactor线程模型-主从Reactor多线程模型。

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

主从Reactor多线程模型

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

主从Reactor线程模型的特点是:服务端用于接收客户端连接的不再是个1个单独的NIO线程,而是一个独立的NIO线程池。Acceptor接收到客户端TCP连接请求处理完成后(可能包含接入认证等),将新创建的SocketChannel注册到IO线程池(sub reactor线程池)的某个IO线程上,由它负责SocketChannel的读写和编解码工作。Acceptor线程池仅仅只用于客户端的登陆、握手和安全认证,一旦链路建立成功,就将链路注册到后端subReactor线程池的IO线程上,由IO线程负责后续的IO操作。

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

各自适用场景

NIO适用场景

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

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

BIO适用场景

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

Java IO:BIO和NIO区别及各自应用场景相关推荐

  1. 【IO】Java 的 BIO、NIO 区别对比

    1.面向流与面向缓冲 Java NIO 和 BIO 之间第一个最大的区别是,BIO 是面向流的,NIO 是面向缓冲区的. Java BIO 面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它 ...

  2. Java IO BIO NIO

    Java IO BIO NIO 一.Java I/O概述 1.1 什么是流 1.2 流的分类 1.3 字符流 1.3.1 Reader 1.3.2 Writer 1.4 字节流 1.4.1 Input ...

  3. java nio 李林峰_浅谈Java中BIO、NIO和AIO的区别和应用场景

    最近一直在准备面试,为了使自己的Java水平更上一个档次,拜读了李林峰老师的<Netty权威指南>,了解了Java关于IO的发展和最新的技术,真是受益匪浅,现在把我总结的关于BIO.NIO ...

  4. JAVA IO : BIO NIO AIO

    JAVA IO : BIO NIO AIO 同步异步.阻塞非阻塞概念 同步与异步 阻塞与非阻塞 IO VS NIO VS AIO 面向流与面向缓冲 阻塞与非阻塞IO BIO.NIO.AIO的JAVA实 ...

  5. java实践11之网络IO BIO和NIO(上)

    文章目录 java实践11之网络IO BIO和NIO(上) 1 BIO: BIO的使用demo 优化版使用线程池实现异步处理 为何已经异步处理了还说BIO是阻塞的? BIO带来的问题 2 NIO ja ...

  6. bio linux 创建_不断升级,Java之BIO、NIO、AIO的演变

    一.前言 一句话概括BIO NIO AIO: 第一阶段,服务端采用同步阻塞的BIO: 第二阶段,服务端采用同步阻塞的线程池的BIO: 第三阶段,JDK4之后服务端采用同步非阻塞的NIO: 第四阶段,J ...

  7. 谈谈java的bio、nio、aio模型

    目录 socket IO(BIO)和NIO的区别 同步和异步 bio:同步阻塞式IO NIO:同步非阻塞IO(工作中用的很少) Buffer使用 NIO代码 AIO socket Socket又称&q ...

  8. java基础IO BIO、NIO、AIO的区别

        Java IO(Java数据流)主要就是Java用来读取和输出数据流.它有对应的一系列API.主要是java.io.*,和java.nio.*. Java中IO主要有两类 |-->字节流 ...

  9. 常见的 IO 模型有哪些?Java 中 BIO、NIO、AIO 的区别?

    IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...

最新文章

  1. Linux sar性能分析
  2. nyoj-754--黑心医生
  3. 小红书起诉4家涉虚假种草通告平台及MCN机构,索赔1000万
  4. 车辆动力学及控制_传统汽车的稳定性控制系统主要通过各个车轮制动进行短暂动作...
  5. java 执行oracle命令_利用oracle存储过程执行操作系统命令
  6. 哥尼斯堡的“七桥问题” (25 分)(DFS)
  7. 倍福PLC TwinCAT 3 基础——编程基础
  8. 蒙德里安的梦想 状态压缩DP (1)
  9. Python用QQ邮箱发送邮件,支持抄送和附件
  10. cups linux 升级_linux cups版本
  11. 数据仓库实践-拉链表设计
  12. 我爱赚钱吧:你知道自己建网站可以赚钱吗?①
  13. 1055 mysql_mysql异常ERROR 1055 (42000)说明
  14. POJ 1877 Flooded! G++
  15. 做眼镜识别的人脸检测
  16. 淘宝订单、API获取订单
  17. Multisim软件的基本使用
  18. 驱动专题:第五章MTD及Flash驱动 4.Norflash驱动
  19. miniui的列数据渲染
  20. Rstudio做多元统计分析R语言

热门文章

  1. VSCode安装及配置
  2. 标签打印软件如何设置不规则标签纸
  3. AD(Altium Designer)PCB布线中的“格式刷”,助力快速布局布线
  4. 数据类型---C语言变量的定义与初始化
  5. 计算机维修技术在线阅读,西南大学19秋[0240] 计算机维修技术在线作业
  6. jndi weblogic mysql_WebLogic配置JNDI数据源及在项目的使用方法
  7. js去掉最后一个逗号
  8. 宝塔Linux面板redis服务开多个端口
  9. 2021年全国在映影院数量、观影人次及平均票价走势分析[图]
  10. 网络工程师面试题(面试必看)(4)