企业网站建设的注意事项,专业点的网站制作公司,wordpress微名片模板,中介用什么软件抓取房源I/O 一直是很多Java同学难以理解的一个知识点#xff0c;这篇帖子将会从底层原理上带你理解I/O#xff0c;让你看清I/O相关问题的本质。
1、I/O的概念
I/O 的全称是Input/Output。虽常谈及I/O#xff0c;但想必你也一时不能给出一个完整的定义。搜索了谷哥欠#xff0c;发…I/O 一直是很多Java同学难以理解的一个知识点这篇帖子将会从底层原理上带你理解I/O让你看清I/O相关问题的本质。
1、I/O的概念
I/O 的全称是Input/Output。虽常谈及I/O但想必你也一时不能给出一个完整的定义。搜索了谷哥欠发现也尽是些冗长的论述。要想厘清I/O这个概念我们需要从不同的视角去理解它。
1.1、计算机结构的视角
根据冯.诺依曼结构计算机结构分为 5 大部分运算器、控制器、存储器、输入设备、输出设备。其中输入是指将数据输入到计算机的设备比如键盘鼠标输出是指从计算机中获取数据的设备比如显示器以及既是输入又是输出设备硬盘网卡等。 用户通过操作系统才能完成对计算机的操作。计算机启动时第一个启动的程序是操作系统的内核它将负责计算机的资源管理和进程的调度。换句话说操作系统负责从输入设备读取数据并将数据写入到输出设备。
1.2、程序应用的视角
根据大学里学到的操作系统相关的知识为了保证操作系统的稳定性和安全性一个进程的地址空间划分为 用户空间User space 和 内核空间Kernel space 。
应用程序作为一个文件保存在磁盘中只有加载到内存到成为一个进程才能运行。应用程序运行在计算机内存中必然会涉及到数据交换比如读写磁盘文件访问数据库调用远程API等等。但我们编写的程序并不能像操作系统内核一样直接进行I/O操作。
从应用程序的视角来看的话我们的应用程序对操作系统的内核发起 IO 调用系统调用操作系统负责的内核执行具体的 IO 操作。也就是说我们的应用程序实际上只是发起了 IO 操作的调用而已具体 IO 的执行是由操作系统的内核来完成的。
但操作系统向外提供API其由各种类型的系统调用System Call组成以提供安全的访问控制。所以应用程序要想访问内核管理的I/O必须通过调用内核提供的系统调用(system call进行间接访问。
所以I/O之于应用程序来说强调的通过向内核发起系统调用完成对I/O的间接访问。换句话说应用程序发起的一次IO操作实际包含两个阶段
IO调用阶段应用程序进程向内核发起系统调用。IO执行阶段内核执行IO操作并返回。准备数据阶段内核等待I/O设备准备好数据拷贝数据阶段将数据从内核缓冲区拷贝到用户空间缓冲区。
UNIX 系统下 IO 模型一共有 5 种
同步阻塞 I/O、同步非阻塞 I/O、I/O 多路复用、信号驱动 I/O异步 I/O。
推荐孙卫琴老师的书籍
2、BIO (Blocking I/O)
应用程序中进程在发起IO调用后至内核执行IO操作返回结果之前若发起系统调用的线程一直处于等待状态则此次IO操作为阻塞IO。阻塞IO简称BIOBlocking IO。其处理流程如下图所示 从上图可知当用户进程发起IO系统调用后内核从准备数据到拷贝数据到用户空间的两个阶段期间用户调用线程选择阻塞等待数据返回。
因此BIO带来了一个问题如果内核数据需要耗时很久才能准备好那么用户进程将被阻塞浪费性能。为了提升应用的性能虽然可以通过多线程来提升性能但线程的创建依然会借助系统调用同时多线程会导致频繁的线程上下文的切换同样会影响性能。所以要想解决BIO带来的问题我们就得看到问题的本质那就是阻塞二字。
3、NIO (Non-blocking/New I/O)
Java NIO 全称 Java non-blocking IO是指 JDK 提供的新 API。从 JDK1.4 开始Java 提供了一系列改进的输入/输出的新特性被统称为 NIO即 NewIO是同步非阻塞的。
那解决方案自然也容易想到将阻塞变为非阻塞那就是用户进程在发起系统调用时指定为非阻塞内核接收到请求后就会立即返回然后用户进程通过轮询的方式来拉取处理结果。也就是如下图所示 应用程序中进程在发起IO调用后至内核执行IO操作返回结果之前若发起系统调用的线程不会等待而是立即返回则此次IO操作为非阻塞IO模型。非阻塞IO简称NIONon-Blocking IO。
然而非阻塞IO虽然相对于阻塞IO大幅提升了性能但依旧不是完美的解决方案其依然存在性能问题也就是频繁的轮询导致频繁的系统调用会耗费大量的CPU资源。比如当并发很高时假设有1000个并发那么单位时间循环内将会有1000次系统调用去轮询执行结果而实际上可能只有2个请求结果执行完毕这就会有998次无效的系统调用造成严重的性能浪费。有问题就要解决那NIO问题的本质就是频繁轮询导致的无效系统调用。
3、AIO (Non-blocking/New I/O)
AIO 也就是 NIO 2。Java 7 中引入了 NIO 的改进版 NIO 2,它是异步 IO 模型。
异步 IO 是基于事件和回调机制实现的也就是应用操作之后会直接返回不会堵塞在那里当后台处理完成操作系统会通知相应的线程进行后续的操作。 目前来说 AIO 的应用还不是很广泛。Netty 之前也尝试使用过 AIO不过又放弃了。这是因为Netty 使用了 AIO 之后在 Linux 系统上的性能并没有多少提升。
4、总结
I/O 其关键点是要将应用程序的IO操作分为两个步骤来理解IO调用和IO执行。IO调用才是应用程序干的事情而IO执行是操作系统的工作。在IO调用时对待操作系统IO就绪状态的不同方式决定了其是阻塞或非阻塞模式在IO执行时线程或进程是否挂起等待IO执行决定了其是否为同步或异步IO。