I/O 的实际操作由内核执行,其中一个重要手段是缓冲区。简单来说 I/O 可分为两类:面向磁盘和面向网络,Java 也是针对这两者来抽象设计 API,相关的类主要在 java.iojava.nio 包中,简称为 BIO 和 NIO。

为什么设计 NIO

一个直接原因就是为了更好的利用操作系统特性,改善和扩展原有 API。与 NIO 相关的规范有两个:

  • JSR 51:它是 NIO 的第一个规范,关注缓冲区、通道和字符集的设计,引入一个简单的面向缓冲区的 I/O 模型,并且提供一套非阻塞、I/O 多路复用、可扩展的 API;
  • JSR 203(NIO.2):它在前者的基础上,添加新的文件系统的抽象,完善现有 Socket 通道的配置,添加多播数据报的支持,并且定义了一个异步 I/O 编程 API。

那么,传统的 BIO 又有什么弊端?NIO 又是如何改进的?

文件操作

关于 java.io.file,它的不足之处在于:

  • 当查询文件属性时,如修改时间或文件类型,都会发生系统调用,并且这些组合操作非常常见,造成性能问题;
  • 部分方法在发生错误时返回 false 而不是抛出异常,比如 delete、rename;
  • 一些 OS 常用功能不支持,比如符号链接、文件锁定、内存映射等。

而 NIO 支持批量获取文件属性,对文件、目录的处理也重新设计,提供 FileLock、MappedByteBuffer。

网络通信

传统 BIO 是阻塞式、基于流的I/O,其网络服务器模型是一连接一线程,通常采用线程池优化,但一个进程或者计算机打开的线程数是有限的,可扩展性差。

NIO 是基于缓冲区(也是由字节流或字符流组成)的,对原始 I/O 提供了新的抽象 - Channel(通道)。Channel 表示一个到硬件设备、文件或网络套接字的连接,与 java.net.Socket 的区别是:

  • 可配置非阻塞,允许事件驱动的设计,提供了一种更加可扩展的服务器开发;
  • 面向字节缓冲区,可实现 零拷贝 执行 I/O ,一端得是 FileChannel。

NIO 主要目标是设计、开发可扩展/可伸缩性服务器,让少量的线程管理大量的客户端连接,而灵活的代价是编程复杂,常用的框架是 Netty,这里想到一个问题,Netty 宣称的零拷贝与OS级别的有区别吗?

服务器常用的优化手段是对象池、减少数据复制(内核到用户进程或用户进程内部)、减少上下文切换和锁,ByteBuffer 本质就是提供了一个可复用的 byte[] 数组,而 BIO 做好这些优化也不见得比 NIO 慢,那么如何选择I/O模型?

I/O 模型的选择

首先了解一下 C10k problem - 描述单机处理1万个并发连接的问题,两个不同的概念:

  • 并发连接(concurrent connections):在有限的时间内响应请求,关注高效的连接调度;
  • 每秒请求数(requests per second):快速处理请求以响应,关注高吞吐量。

C10k 问题的本质在于 CPU,即线程数,单机创建大量线程,不仅占用大量的内存,频繁的数据复制和上下文切换还会导致 OS 崩溃。

如果采用 BIO 一个直观的解决办法是水平扩展,采用分布式系统,但如果并发量上升到百万、千万、甚至上亿,那么服务器的成本得多大?解决此问题的关键是减少线程数,提高单机的处理能力,而如何使用少量的线程管理大量的连接,则在操作系统层面解决了,也就是 Linux 下的 Epoll,Java 中的 NIO。如果你的应用面临 C10k 问题,NIO 是最好的选择。

那 BIO 有什么用呢?大家都用线程池,你有 ByteBuffer,我也可以自己维护字节缓冲,照样成块读取,阻塞无非因为 I/O 延迟高,那换成 SSD和光纤,而且我编程简单,唯一的缺点就是扩展性差了点。:)

至于如何选择 I/O 模型,需要结合业务场景,综合考虑:

  • 短连接还是长连接
  • 预计最大的并发数
  • 预计每个连接的数据量,即流量的大小

但感觉还是很难给出明确的答案,简单来说,并发量低的可采用 BIO,高的可采用 NIO,至于 AIO 它应该不太成熟,不过多描述了。

小结

上文强调了 BIO 可扩展性差,那么什么是可扩展性?参考 wiki-Scalability 对它的描述,简单概括如下:

Scalability 是系统,网络或进程处理越来越多的工作的能力,或者它可以(水平或垂直)扩展以适应这种增长的潜力。例如,如果系统在添加资源(通常是硬件)时能够在负载增加下增加其总输出,则认为该系统是可扩展的。

而 BIO 的性能和连接数与机器性能的关系往往是非线性的。

转载于:https://juejin.im/post/5b5d6527e51d45190f4adb04

关于 IO 和 NIO 的思考相关推荐

  1. Android性能优化--IO 优化( IO基本知识:应用程序、文件系统和磁盘,三种IO方式及适用场景,多线程阻塞IO和NIO)

    目录 I/O 的基本知识 1. 文件系统 2. 磁盘 Android I/O 1. Android 闪存 2. 两个疑问 疑问一:文件为什么会损坏? 疑问二:I/O 有时候为什么会突然很慢? 不同的场 ...

  2. Java之IO,BIO,NIO,AIO

    2019独角兽企业重金招聘Python工程师标准>>> 参考文献一 IO基础知识回顾 java的核心库java.io提供了全面的IO接口.包括:文件读写.标准设备输出等.Java中I ...

  3. io读取一个文件再写入socket技术_JAVA中IO与NIO面试题

    BIO.NIO有什么区别? BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低. NIO:New IO 同步非阻塞 IO,是传统 IO ...

  4. Java传统的io和nio区别_Java中IO和NIO的本质和区别

    简介 终于要写到java中最最让人激动的部分了IO和NIO.IO的全称是input output,是java程序跟外部世界交流的桥梁,IO指的是java.io包中的所有类,他们是从java1.0开始就 ...

  5. 五.Java IO、NIO、文件、通讯

    2019独角兽企业重金招聘Python工程师标准>>> Java 的 I/O 大概可以分成四组: 基于字节操作的 I/O :InputStream 和 OutputStream 基于 ...

  6. NIO详解(十三):Java IO 和NIO 总结

    1. 概述 下面总结了Java NIO和IO之间的主要差别 IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器 2. Java IO和 NIO的主要区别 2.1 面向流和面向缓冲区 Ja ...

  7. Java NIO:IO与NIO的区别

    一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...

  8. IO: BIO ? NIO ? AIO?

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...

  9. Java与汽车_Java NIO:IO与NIO的区别

    一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...

最新文章

  1. html列表中float-left,floatleft的作用
  2. java 对象 jvm生命_JVM对象的生命周期
  3. 导出到Excel的操作
  4. 一次mysql大数据量查询 慢查询导致服务阻塞后的学习
  5. 3_9 VisitorMode 访问者模式
  6. 十天学Linux内核之第七天---电源开和关时都发生了什么
  7. 9 PP配置-生产主数据-工作中心相关-定义工序控制码
  8. iptables 一些有用的规则
  9. Bootstrap3 表单
  10. C开源hash代码uthash的用法总结(2)
  11. 模板题——前缀和与差分
  12. C++ string append方法的常用用法
  13. 计算机图形学上机(一)改进的DDA算法
  14. 【Win7系统 沙滩啤酒桌面主题】
  15. Cocos2d-x制作《单机斗地主》源码解剖5:玩家的出牌
  16. 第6章 为用户编程:终端控制和信号
  17. 如何区分前后端 BUG
  18. selenium操作360极速浏览器的方法
  19. windows下图像标注软件Labelme安装及使用教程
  20. [7 kyu] Exes and Ohs

热门文章

  1. CAP原理和最终一致性(Eventually Consistency)
  2. chrome的cookies
  3. 这里90%的程序员根本就不算程序员。
  4. Unity+KBEngine实战系列1——棋牌(含完整教程与源码)
  5. Docker(十八)基于python3.5 以apline 为系统的python 环境
  6. Spring boot如何打war包发布到tomcat
  7. 配置web.xml和glassfish容器实现javaEE表单验证
  8. Nexus1000v部署
  9. 【云栖大会】“天”与“人”的大数据
  10. ElasticSearch入门系列(一)是什么以及安装和运行