一文让你了解透彻Java中的IO模型

 更新时间:2023年05月04日 08:37:03   作者:小小小小明明明明明明明明  
本文只是说明了IO模型,让你了解IO模型是什么,怎么区分IO模型,以及分析了Java中的三种IO模型,本文是纯理论知识,看完之后会让你对IO有更加深刻的理解,感兴趣的同学可以参考一下

什么是IO

IO(Input/Output),也就是输入和输出的简称,从计算机结构的角度来看,IO,就是输入数据到计算机中,计算机输出数据到计算机外,下面有一张十分经典的冯·诺伊曼结构图,将计算机分为五大部分:运算器、控制器、存储器、输入设置、输出设备。

输入设备向计算机输入数据,输出设备接收计算机输出的数据。

所以,从计算机结构的角度来看IO,IO就是描述了计算机系统和外部设备之间通信的过程

接下来我们再从应用程序的角度去了解一下IO:在操作系统中,为了保证操作系统的稳定性和安全性,一个进程的地址空间被划分为了用户空间(User space)和内核空间(Kernel space)

那么什么是用户空间,什么是内核空间呢?

  • 用户空间是普通应用程序可访问的内存区域。
  • 内核空间是操作系统内核访问的区域,独立于普通的应用程序,是受保护的内存空间。

可以简单的理解为我们平常运行的应用程序,都是运行在用户空间中的,它没有权限去进行一些系统态级别的资源相关操作,比如文件管理、内存管理、等等,这些操作都是要依赖内核空间才能完成,也就是说,我们如果想要进行IO操作,一定是要依赖内核空间的能力,并且这里需要注意一点:用户空间的程序不能直接访问内核空间

那么如果要发起一次IO操作,那应该怎么办呢?

当我们需要执行一次IO操作的时候,由于没有执行IO操作的权限,只能发起系统调用请求操作系统来帮忙完成,所以用户进程想要执行IO操作的话,必须通过系统调用来间接的访问内核空间,比如我们最常见的IO操作就是磁盘IO(读写文件)和网络IO(网络请求和响应)。

那么从应用程序的视角去看IO的话,我们的应用程序发起对操作系统的内核发起IO调用(系统调用,注意只是调用),操作系统去负责内核执行具体的IO操作。(如果这段话不是很好理解,可以理解为调包,比如别人写好了的工具类,我们不需要关注里面的实现细节,只需要调用它的方法就好了,这里我们的应用程序就是发起了一个调用,但是真正执行的还是我们的操作系统)

当应用程序发起IO调用之后,会经历下面两个步骤:(这里一定要记住这两点,它和后面息息相关!)

  • 内核等待IO设备准备好数据
  • 内核将数据从内核空间拷贝到用户空间

常见的IO模型

IO模型有很多种(比如在UNIX系统下,IO模型一共分为5种:同步阻塞IO、同步非阻塞IO、IO多路复用、信号驱动IO、异步IO),本篇文章只讲述Java中的IO模型,Java中的IO被分为三类:BIO、NIO、AIO

BIO(Blocking IO)

BIO属于同步阻塞IO模型,应用程序发起read调用之后,会一直阻塞,直到内核把数据从内核空间拷贝至用户空间。

BIO就是Java中最传统的IO模型,相关的类和接口都在java.io这个包下面,因为现在用的人很少(后面看它的特点就知道为什么了),所以我们这里简单介绍一下它的一些特点就好了。

  • 对高并发场景下对于线程资源的消耗较高,每一个连接需要使用一条线程单独处理。
  • 传输较小对象时存在频繁的线程上下文切换等性能问题。

如何优化

那么怎么去优化这个BIO呢?

首先上面说了BIO的缺点之一就是它是有多少连接就需要多少线程的模型,但是对于用户来说,打开一个连接,然后关闭一个连接是十分常见且频繁的事情,而与之对应的就是创建线程和销毁线程,但是创建线程和销毁线程对于操作系统来说是十分消耗资源的,所以想到的优化就是使用线程池去进行优化BIO。

NIO的面世

但是BIO的模型决定了它的上限,它始终是同步阻塞的IO模型,阻塞就会导致不能使用单线程处理多个请求,所以这个时候就需要修改它的模型,将调用read()、write()方法不再是阻塞的,这样就可以使用单线程处理多个请求,而这样就不再是同步阻塞的IO模型了,也就是我们下面要说到的NIO了。

NIO(Non-blocking/New IO)

Java的NIO是Java1.4引入的,对应的是java.nio包,提供了channel、selector、buffer等抽象。

Java中的NIO可以看作是IO多路复用模型,但是也有人认为它是同步非阻塞IO模型,这里我们先简单介绍一下这两种模型:

同步非阻塞IO模型

这个相比同步阻塞IO模型,同步非阻塞IO模型就是通过轮询的方式,避免了一直阻塞

但是从图中也能看出问题所在,就是应用程序不断的进行IO系统调用轮询数据是否已经准备就绪的这段时间,是十分消耗CPU资源的(说白话就是反复调用read操作)

所以这个时候就引入了IO多路复用模型。

IO多路复用模型

在IO多路复用模型中,线程首先发起select调用,询问内核数据是否准备就绪,等待内核把数据准备好了,会返回一个ready调用,告诉你,我准备好了,这个时候用户线程再发起read调用。注意:read调用的过程依然是阻塞的(数据从内核空间拷贝至用户空间这段时间)

IO多路复用模型通过无效的系统调用,减少了对CPU资源的消耗

Java中的NIO

Java中的NIO,有一个十分重要的概念,就是选择器(selector),也被称为多路复用器,通过它就可以实现使用一个线程管理多个客户端连接(这里是不是和BIO就不一样了,最大的优化的点就在这里) 。当客户端数据到了之后,线程再为客户端进行服务。

下面给出一张JavaNIO的图:

这张图就能很好的说明了NIO的特点了。

AIO(Asynchronous IO)

AIO,也被称为NIO 2.0,Java7中引入的异步IO模型,很多人都不理解非阻塞IO和异步IO到底有什么差别,其实异步IO就是基于事件和回调机制去实现的,也就是说用户调用操作之后会立马返回,不会阻塞,当后台处理完成,操作系统会通知相应的线程进行后续操作

目前来说AIO的应用还没有十分广泛,应用最多的是NIO。

总结

最后放一张图来总结Java中的IO模型:

到此这篇关于一文让你了解透彻Java中的IO模型的文章就介绍到这了,更多相关Java IO模型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法

    Spring Boot报错:No session repository could be auto-configured

    这篇文章主要给大家介绍了关于Spring Boot报错:No session repository could be auto-configured, check your configuration的解决方法,文中给出了详细的解决方法,对遇到这个问题的朋友们具有一定参考价值,需要的朋友下面来一起看看吧。
    2017-07-07
  • springboot读取resource配置文件生成容器对象的示例代码

    springboot读取resource配置文件生成容器对象的示例代码

    这篇文章主要介绍了springboot读取resource配置文件生成容器对象的示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • 浅谈JSON的数据交换、缓存问题和同步问题

    浅谈JSON的数据交换、缓存问题和同步问题

    这篇文章主要介绍了浅谈JSON的数据交换、缓存问题和同步问题,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • 使用@RequestBody传递多个不同对象方式

    使用@RequestBody传递多个不同对象方式

    这篇文章主要介绍了使用@RequestBody传递多个不同对象方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • 实战分布式医疗挂号通用模块统一返回结果异常日志处理

    实战分布式医疗挂号通用模块统一返回结果异常日志处理

    这篇文章主要为大家介绍了实战分布式医疗挂号系统之统一返回结果统一异常处理,统一日志处理到通用模块示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-04-04
  • springboot配置templates直接访问的实现

    springboot配置templates直接访问的实现

    这篇文章主要介绍了springboot配置templates直接访问的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • maven私服搭建与使用教程

    maven私服搭建与使用教程

    在使用maven进行Java项目的开发过程中,难免会有些公共的私有库,这些库是不太方便放到中央仓库的,可以通过Nexus搭建一个私有仓库,这篇文章主要介绍了maven私服搭建与使用,需要的朋友可以参考下
    2023-03-03
  • java数据结构与算法之noDups去除重复项算法示例

    java数据结构与算法之noDups去除重复项算法示例

    这篇文章主要介绍了java数据结构与算法之noDups去除重复项算法实现技巧,程序代码非常简单,关键在于循环与判定,需要的朋友可以参考下
    2016-08-08
  • java构造器复用方式

    java构造器复用方式

    这篇文章主要介绍了java构造器复用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Spring Boot使用过滤器Filter过程解析

    Spring Boot使用过滤器Filter过程解析

    这篇文章主要介绍了Spring Boot使用过滤器Filter过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01

最新评论