IO输入输出模型是每个Java开发人员必须理解的重点

这种预连接的流通常有标准输入,标准输出和标准错误流。

最常见的实现了编解码功能的就是我们常说的标准流,Java编程中我们从java.system中能够看到in,out,err等标准I/O流的定义。

标准输入默认从键盘读取它的输入。

标准输出和标准错误默认将它们的输出到屏幕上。

数据流的分类

======

说到数据流就不得不说我们常见的数据流类型,通常我们处理的数据主要分为两种类型,一种是基于文件存储块的块类型数据流,另一种是基于网络字节流的流类型数据流。

而我们编写的几乎所有的应用程序都会或多或少的涉及到这两种类似数据流的处理,当然也有极少数特殊的应用程序不需要我们操作数据流。

我们知道计算机操作系统中是以文件系统作为数据存储和操作的基础组件的,文件系统设计是基于数据存储的物理磁盘结构来设计的,因为磁盘是以固定的分区块来管理数据存取的。

所以基于文件的数据流都是面向块操作的数据流,而像基于网络访问的数据流动则是面向字节流的数据流。

很明显面向块的数据流处理要比面向流的数据处理要快速。

IO输入输出模型是每个Java开发人员必须理解的重点

关于NIO模型

=======

前面讲到Java开发最初对于I/O的支持模式是单线路的,也就是说需要CPU全程参与数据读取过程。每个数据输入或者输出的处理线程都需要CPU来阻塞执行。即一旦开始读写,CPU将等待其结束,然后才能进行其它任务执行。

随着技术的发展,NIO模型的出现,该模型巧妙的设计了一个内存缓冲区和通道概念,将原来针对具体数据流的操作,封装成了对于缓冲区的操作。并将所有操作都抽象到一个通道模型里。

其中引入的缓冲区概念Buffer是新一代输入输出操作模型的基础,它本质上是一块内存空间的抽象,并将其具体的操作指令化封装给连接到它的通道Channel上。

由通道来封装跟这内存区域关联的数据源或者目的地。通道的read()和write()方法来触发CPU对读写事件的响应处理。

具体就是在read()指令发出后,操作系统会将数据从数据源读入到指定的缓冲区里,而当write()指令发出后,则会将连接到该通道的缓冲区数据排空出缓冲区到指定的数据目的地。

如此我们就不难理解,我们可以将基于任意数据源建立的流封装成对应的数据通道,然后为通道指定连接的缓冲区,接下来就是发送相关指令来进行目标数据的操作了。

我们使用Java编写的所有应用程序都是受到JVM进程管理的,所以跟操作系统的通信也是有JVM负责完成的。

JVM在执行I/O时,通过请求操作系统执行一个write操作排空缓冲区内容到存储器,使用一个读操作来从存储设备读取数据填充缓冲区空间。

假设我们的读操作包含一个硬盘驱动步骤,操作系统会发布一个命令给硬盘控制器来从硬盘上读取一个字节块到操作系统的缓冲区。

一旦这一操作完成,操作系统会拷贝其缓冲区的内容到由我们发起的read()操作的进程指定的缓冲区里。

如果我们的应用程序进程发布一个read()方法调用操作系统,那么操作系统会请求硬盘控制器来从硬盘上读取数据字节块。

IO输入输出模型是每个Java开发人员必须理解的重点

DMA技术问题

=======

这里硬盘控制器就是通过前面提到的直接内存访问技术(DMA)来将数据从硬盘读取到操作系统的缓冲区里。

因为DMA能够允许特定的硬件子系统独立于CPU而直接访问主系统内存。

其实,这种从操作系统缓冲区拷贝字节到应用程序进程缓冲区并不是一个高效的方式。

如果让DMA控制器直接将数据拷贝到进程缓冲区会更高效,但是我们在用它编程过程中会遇到两个问题:

DMA控制器通常不能直接跟运行JVM进程的用户空间进行交互,它只能跟操作系统的内核空间交互。

一般面向块存储的设备,其操作的数据块是固定大小的,而我们应用程序的JVM进程可能需要的数据类型大小不一定就是存储块的倍数,这就会出现数据流类型的错配。

所以,必须在直接访问控制器的数据与具体应用程序的数据之间有一个适配过程,而这个过程就是由我们的操作系统来执行的。

通常我们的操作系统会在JVM进程和DMA控制器之间数据转换时对数据进行分解和重组,使得它们之间能够顺畅的通信。

IO输入输出模型是每个Java开发人员必须理解的重点

NIO三要素:缓冲器,通道,就绪选择器

===================

NIO使得CPU从过去的I/O导向型CPU工作中解放来,交给了各种可以直接进行内存访问设备的控制器来负责输入输出工作。

而通道Channel概念的引入,使其跟设备控制器有更好的通信交流,来更加高效的向应用程序的缓冲区里填充数据或将应用程序的字节缓冲区排空。

同样的Java为我们提供了对这一概念的抽象接口定义Channel,作为封装了基础数据流操作的基础接口。

我们常见的具体通道定义比如FileChannel,SocketChannel,DaragramChannel等,都是对具体类型流封装后连接特定缓冲区的通道。

就绪选择器

前面我们提到过,I/O可分为面向块的或面向流的两类。

从文件中读取数据或者将数据写入到文件中是一个面向块的I/O实例。

相反的,从键盘读取或者将数据写入到网络连接中的实例是一个面向流的I/O实例。

面向流的I/O通常比面向块的I/O速度慢,此外,输入往往是断断续续的,原因可能是用户可能会在输入字符流时暂停了,或者在网络连接中出现短暂的慢速,导致播放视频断断续续地进行。

现代操作系统在处理面向流数据处理时,我们不再像传统的I/O模型那样阻塞CPU等待输入和输出工作完成,而是采用非阻塞模式,CPU在启动了设备控制器后就会转而处理其它任务,而让一个线程不断的去轮询其处理状态,但是这种轮询也是对CPU资源的浪费,特别是要同时监控多个输入输出工作运行状态时。

IO输入输出模型是每个Java开发人员必须理解的重点

此时就引入了一个新的概念叫做就绪选择,而Java对此抽象出了Selector。

操作系统以非阻塞模式来监视所有流处理的集合,并返回一个指示,告诉线程哪些流已经准备就绪执行I/O。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

分享

这次面试我也做了一些总结,确实还有很多要学的东西。相关面试题也做了整理,可以分享给大家,了解一下面试真题,想进大厂的或者想跳槽的小伙伴不妨好好利用时间来学习。学习的脚步一定不能停止!

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Cloud实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

Spring Boot实战

薪酬缩水,“裸辞”奋战25天三面美团,交叉面却被吊打,我太难了

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

Spring Boot实战

[外链图片转存中…(img-4ctXPxqU-1712789407077)]

面试题整理(性能优化+微服务+并发编程+开源框架+分布式)

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-tlU15TFF-1712789407078)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值