深入理解JAVA的IO模型

简介: 深入理解JAVA的IO模型

通俗易懂的来讲,个人比较喜欢把io理解成对于文件中的数据进行读取或者修改的一种途径。


关于io的那些具体代码该如何编写,本文不打算进行具体展示,因为代码案例很多在网上一搜就有,所以直接忽略。


(作为程序员,基本的搜索能力还是要有的)

 

个人对于io的认识



每次读取数据都开启一个通道,然后用一个载体去读取文件里面的内容,然后将文件里面的数据运输回到程序里面。


那么载体的种类可能为字节,也可能是以缓冲的形式来读取数据,因此这个时候又分为了面向字节面向缓冲的形式来读取数据。

 

面向字节读取数据



网络异常,图片无法展示
|


如图所示,一次运输一个字节,所以效率会比较底下。常见的字节流都是以这种方式读取和修改数据信息的。


FileInputStream,ObjectInPutStream,PipedOutputStream,ByteArrayInputPutStream...

面向缓冲读取数据


网络异常,图片无法展示
|


面向缓冲的形式对数据内容读取的效率会较高,原因在于buffer会预先读取一定的字节内容,传输到程序中,读取效率会有所提升。

 

IO操作的时候计算机内部到底发生了什么?



在较早的计算机里面,读取磁盘汇总的数据的请求通常都是由一个程序发起的,首先会请求用户的地址空间(这里面存储了buffer数据)再去请求内核地址空间的内容。用户的内核地址空间和os的内核地址空间之间进行数据copy。内核地址空间需要去请求文件的io接口,读取数据。


网络异常,图片无法展示
|


但是每次内核地址空间去请求文件的io接口的时候,都需要cpu分出精力来处理io请求,因此会对cpu造成较大的压力。


于是随着技术的进步,后边出现了一种技术叫做dma总线技术,将io接口请求的任务分配给了dma和内存处理,减轻了cpu的压力。


网络异常,图片无法展示
|


假设当大量的请求发送过来之后,dma每次运行的时候都需要向cpu申请资源,创建dma总线。但是如果dma总线过多,容易发生冲突,因此会有性能影响。(申请资源需要排队)


因此后边又有了技术改善,dma拥有了自己的内存,专门用于进行io操作,有自己的命令和传输方式,不需要向cpu申请资源。


 

非直接缓冲区



jdk早期版本的是数据读取过程中,实际上是需要经历如下的一个过程


网络异常,图片无法展示
|


java程序并非直接就有权利去读取磁盘里面的数据,需要通过磁盘文件的io接口将数据传输到内核地址的缓存区,然后通过拷贝的形式将数据拷贝到用户地址的缓存区,再从用户地址里面的缓存区域进行数据的拷贝,从而实现io的数据读取。(通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间)

 

直接缓冲区



在jdk1.4之后出现了new io,也就是我们常说的nio,它的运行效率高的原因之一就是使用了直接缓冲区。让jvm直接将部分的内存存储在了物理内存里面,避免了原来的jvm和os之间进行数据copy的性能消耗。


但是这样也有一定的缺点,那就是数据的安全性没有给os来进行管理,有一定的危险(例如病毒程序的篡改)。有时候程序里面的大对象存储也会使用堆外内存来保存,也是这种原理。(不占用jvm内存)如下图所示:


网络异常,图片无法展示
|


阻塞和非阻塞



Java的Io的各种流是阻塞的,当某个线程执行io这类操作的时候,都会进入一个堵塞的状态,直到有相应的数据读取或者全部写入完毕之后才阻塞结束。


随着jdk的发展,逐渐出现了nio技术,这是一种基于非阻塞模式的处理手段。当有线程进行数据的读写的时候,会有单独的线程来进行对于多个管道的输入输出管理。

 

同步io vs. 异步io



同步I/O:当有一连串的io请求需要处理的时候,无法并发的执行,需要进行排队等候。

异步I/O:用户线程发起I/O请求后仍然继续执行,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

 

字节流和字符流



早期版本的jdk里面提供了字节流和字符流两种类型,字符流在处理数据的时候是基于字符的形式,比原始的字节速度要高些,但是在处理一些类似于图片这类的数据的时候却无从下手。(因为图片的编码格式和常规的字符流编码格式不一致)。因此字符流和字节流各有各的优势,并不能说被任一方所替代。

 

总结



个人觉得io是java程序猿向高端进阶的一门比较吃力的学问了,从原始的bio发展到现在的nio,aio。netty,mina等一系列高性能io框架出来之后,市场的实际应用份额也越来越高。包括现有的很多rpc框架,例如说阿里的dubbo,名声赫赫的Tomcat,Jetty等服务器,很多都是基于io的技术基础进行升级研发的。

目录
相关文章
|
1月前
|
网络协议 前端开发 Java
网络协议与IO模型
网络协议与IO模型
网络协议与IO模型
|
1月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
69 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
1月前
|
安全 NoSQL Java
一文搞懂网络通信的基石✅IO模型与零拷贝
【10月更文挑战第1天】本文深入探讨了网络通信中的IO模型及其优化方法——零拷贝技术。首先介绍了IO模型的概念及五种常见类型:同步阻塞、同步非阻塞、多路复用、信号驱动和异步IO模型。文章详细分析了每种模型的特点和适用场景,特别是多路复用和异步IO在高并发场景中的优势。接着介绍了零拷贝技术,通过DMA直接进行数据传输,避免了多次CPU拷贝,进一步提升了效率。最后总结了各种模型的优缺点,并提供了相关的代码示例和资源链接。
一文搞懂网络通信的基石✅IO模型与零拷贝
|
29天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
18 1
|
1月前
|
开发者
什么是面向网络的IO模型?
【10月更文挑战第6天】什么是面向网络的IO模型?
22 3
|
1月前
|
数据挖掘 开发者
网络IO模型
【10月更文挑战第6天】网络IO模型
42 3
|
1月前
|
缓存 Java Linux
硬核图解网络IO模型!
硬核图解网络IO模型!
|
1月前
|
数据挖掘 开发者
网络IO模型如何选择?
网络IO模型如何选择?【10月更文挑战第5天】
20 2
|
1月前
|
数据库
同步IO模型是一种常见的编程模型
【10月更文挑战第5天】同步IO模型是一种常见的编程模型
20 2
|
2月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
下一篇
无影云桌面