深入理解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的技术基础进行升级研发的。

目录
相关文章
|
5月前
|
Java 大数据 Go
从混沌到秩序:Java共享内存模型如何通过显式约束驯服并发?
并发编程旨在混乱中建立秩序。本文对比Java共享内存模型与Golang消息传递模型,剖析显式同步与隐式因果的哲学差异,揭示happens-before等机制如何保障内存可见性与数据一致性,展现两大范式的深层分野。(238字)
161 4
|
5月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
246 1
|
7月前
|
缓存 前端开发 Java
Java类加载机制与双亲委派模型
本文深入解析Java类加载机制,涵盖类加载过程、类加载器、双亲委派模型、自定义类加载器及实战应用,帮助开发者理解JVM核心原理与实际运用。
|
7月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
7月前
|
SQL Java 数据库连接
Java IO流(一):字节流与字符流基础
本文全面解析Java IO流,涵盖字节流、字符流及其使用场景,帮助开发者理解IO流分类与用途,掌握文件读写、编码转换、异常处理等核心技术,通过实战案例提升IO编程能力。
|
7月前
|
机器学习/深度学习 人工智能 自然语言处理
Java 大视界 -- Java 大数据机器学习模型在自然语言生成中的可控性研究与应用(229)
本文深入探讨Java大数据与机器学习在自然语言生成(NLG)中的可控性研究,分析当前生成模型面临的“失控”挑战,如数据噪声、标注偏差及黑盒模型信任问题,提出Java技术在数据清洗、异构框架融合与生态工具链中的关键作用。通过条件注入、强化学习与模型融合等策略,实现文本生成的精准控制,并结合网易新闻与蚂蚁集团的实战案例,展示Java在提升生成效率与合规性方面的卓越能力,为金融、法律等强监管领域提供技术参考。
|
7月前
|
机器学习/深度学习 算法 Java
Java 大视界 -- Java 大数据机器学习模型在生物信息学基因功能预测中的优化与应用(223)
本文探讨了Java大数据与机器学习模型在生物信息学中基因功能预测的优化与应用。通过高效的数据处理能力和智能算法,提升基因功能预测的准确性与效率,助力医学与农业发展。
|
7月前
|
机器学习/深度学习 搜索推荐 数据可视化
Java 大视界 -- Java 大数据机器学习模型在电商用户流失预测与留存策略制定中的应用(217)
本文探讨 Java 大数据与机器学习在电商用户流失预测与留存策略中的应用。通过构建高精度预测模型与动态分层策略,助力企业提前识别流失用户、精准触达,实现用户留存率与商业价值双提升,为电商应对用户流失提供技术新思路。
|
7月前
|
机器学习/深度学习 存储 分布式计算
Java 大视界 --Java 大数据机器学习模型在金融风险压力测试中的应用与验证(211)
本文探讨了Java大数据与机器学习模型在金融风险压力测试中的创新应用。通过多源数据采集、模型构建与优化,结合随机森林、LSTM等算法,实现信用风险动态评估、市场极端场景模拟与操作风险预警。案例分析展示了花旗银行与蚂蚁集团的智能风控实践,验证了技术在提升风险识别效率与降低金融风险损失方面的显著成效。
|
7月前
|
机器学习/深度学习 自然语言处理 算法
Java 大视界 -- Java 大数据机器学习模型在自然语言处理中的对抗训练与鲁棒性提升(205)
本文探讨Java大数据与机器学习在自然语言处理中的对抗训练与鲁棒性提升,分析对抗攻击原理,结合Java技术构建对抗样本、优化训练策略,并通过智能客服等案例展示实际应用效果。