Java中的常见的 IO 模型

I/O 就是输入和输出,为了保证操作系统的稳定性和安全性,一个进程的地址空间分为用户空间和内核空间。平时运行的应用程序都是在用户空间内,内核空间进行系统级别的资源有关的操作。比如果文件管理,进行通信等。用户空间的程序不饿能直接访问内核空间。

当程序执行 IO 操作时,应用程序发起调用请求让操作系统帮助。

开发中接触的比较多的就是磁盘 IO 、文件读写和 网络 IO、网络请求和响应。

从应用程序来看,应用程序就是向操作系统的内核空间发起调用请求,操作系统的内核执行实际的 IO 操作。相当于应用程序发起 IO 操作的调用,实际 IO 执行是在内核完成的。

应用程序调用之后会有两个步骤:

1. 内核等待 IO 设备准备好资源数据。

2. 内核将准备好的数据从内核空间拷贝到用户空间。

常见的 IO 模型,同步阻塞 IO、同步非阻塞 IO、IO 多路复用、信号驱动 IO、异步 IO 。

这里只看 Java 中常见的模型。

同步阻塞 IO(BIO)

应用程序调用 IO 请求之后,操作系统内核会有从准备数据到数据拷贝的过程,这个过程进程是被阻塞的,当内核将请求返回进程才能继续执行之后的工作。

同步阻塞IO(BIO)就是在应用程序发起 read 调用之后,直到内核将数据拷贝到用户空间时 返回read 请求。整个调用过程是阻塞的。

这种模型在高并发环境下就会性能低下。

同步非阻塞IO (NIO)

简单来说,同步非阻塞就是当应用程序发起 read 调用后,不用等待 IO 设备准备资源数据,而是直接接收内核传来的返回。期间多次访问内核有没有将数据准备好,直到 IO 设备准备好了资源数据,内核就将数据拷贝给用户空间。

这个模型的问题就是,期间多次调用 read,这是会消耗资源的。

考虑到多次调用过多消耗资源,就可以使用 IO 多路复用模型。

IO 多路复用

所谓多路复用,就是将线程多次复用,由一个或者多个线程监控 IO 请求,一旦某个请求就绪了,就通知程序可以进行 IO 操作了,此时就是将内核中的数据拷贝到用户空间了。

目前支持 IO 多路复用的系统调用,由 select、epoll等。首先单个线程不断通过 select / epoll 系统调用轮询连接,当有某个连接地数据准备好了之后,就通知应用程序可以调用了,然后发起 read 调用,将内核中的数据拷贝到用户空间。

IO 多路复用和 NIO 的区别也就是优势,多路复用通过 select / epoll 来监听多个连接,一个线程对应多个任务,而 NIO 是一条线程轮询一个任务。开销明显的减少了。

但是 IO 多路复用在数据拷贝期间仍然是线程阻塞的,这里就可以用到异步 IO (AIO)

异步 IO(AIO)

简单来说,就是用户调用 read 之后直接返回,然后去做其他的事情,数据准备和拷贝都交由内核空间来完成,流程完毕之后,通知用户程序,可以执行之后的操作了。

就好比你加班回家非常饿,家人给你留的饭菜已经冷了,这个时候你又想洗澡放松一下,你就可以调用方法请求到微波炉,微波炉给你返回一个信息告诉你我在给你准备晚饭了,此时你可以先去洗个澡,直到听到微波炉 “ 叮 ” 的响应,然后你就可以开始吃饭了。 

异步 IO 需要底层操作系统的支持,因为大量的工作都是在内核空间完成的。

目前应用不是很广泛,大多数还是使用的多路复用 IO,比如 Redis。

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值