java与IO
2022-04-04 22:31:40 0 举报
AI智能生成
描述Java中IO相关内容。从编程API到系统IO模型。包括他们中间的衔接过程,从API调用到系统调用,用户态到内核态切换。优缺点,资源使用情况等。
作者其他创作
大纲/内容
概述
javaIO模型概述
参考:
https://blog.csdn.net/weixin_34638282/article/details/114082186?ops_request_misc=&request_id=&biz_id=102&utm_term=java%20IO&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-114082186.nonecase&spm=1018.2226.3001.4187
javaIO和系统IO衔接
回归到计算机组成层面回到这个问题
Stream流的驱动力
NIO
JavaIO模型
tips:太多记不住?
站在内存(程序运行在内存中)的角度看命名
*InputStream输入到内存中,因此有read系列方法,将流的字节读取到变量中
*OutputStream从内存中输出,因此有write系列方法,将直接写入到流中。这个流将直接写入到哪了?那是具体实现类的问题
Reader\Writer面向字符,和InputStream、OutputStream最大的区别是中间加了编码
其他的File*,Object*,Pipe*等就对不同源的具体实现类
inputStream.read()方法阻塞吗?
其实InputStream(对应OutputStream不重复强调)是一个非常高的抽象,它只定义了,可以从Stream中读取字节。并不一定会阻塞
比如ByteArrayInputStream,可以直接从直接数组中构造。然后从数组中直接返回read(),这显然是不阻塞的。
哪里给我们read()方法阻塞的错觉?因为大部分时候用到Stream流都直接或间接的连接到系统IO。系统IO会阻塞
这里(直接或间接)就是Stream系用到了装饰者模式
比如FileInputStream.read()方法的注释:
Reads a byte of data from this input stream. This method blocks if no input is yet available.
如果输入还没有准备好?这里隐隐约约已经体现了java程序和系统IO之间的关系。下面我们将在系统IO与程序IO的角度来分析这个问题
JavaIO和系统IO衔接
参考:
https://blog.csdn.net/zuoxiaolong8810/article/details/9974525?utm_source=itdadao&utm_medium=referral
https://blog.csdn.net/qq_42052956/article/details/111562280
java程序在这里阻塞了线程,在等待系统IO准备好数据。CPU在这个时候应该是可以释放出去的,浪费了什么?
系统层面是谁怎么准备好的数据?
线程切换到内核态,等于当前CPU仍然在处理这次读操作。切换到内核态后,完成数据从磁盘空间到内核空间到用户空间的读取,最终返回。将CPU再交给程序进行执行。
java FileInputStream的native read方法中,最终调用的是系统函数Read_File。该函数传入的参数中,包括需要读取的字符长度,需要写入的内存地址。且该方法是同步阻塞的。内部需要完成从磁盘将数据读取到内核,最终写入传入的程序内存地址中。最终返回读取到的字节长度
read的Linux版实现,用的同步阻塞模型。
read()调用的时候,属于系统调用,会导致用户态到内核态转换。CPU使用有用户线程切换到系统线程。
可以理解为CPU还是在处理这次读操作。
对于JVM来说,浪费了什么资源?
线程资源
当前申请的线程资源仍然处于活跃等待中。无法被其他任务使用
并发大的时候需要申请更多的线程资源
对应线程占用的计算机资源,比如内存。系统句柄等
Java线程和系统线程的关系?
jdk1.2之后,Java的线程本质上对应一条系统线程。
对应的,如果线程创建过多,系统消耗将非常大。线程切换的消耗也很大
Stream流的驱动力
Stream流只提供了获取和写入字节等的接口定义。仍然需要程序主动循环读取和写入对应字节。
PipedInputStream管道流使用说明
用在不同线程之间传输数据用的
且强调不要在一个线程中使用
参考
https://blog.csdn.net/zlp1992/article/details/50298195/
outputStream转inputStream问题
问题
一个程序要写一个输出流outputStream,现在需要将这个outputStream,转成一个InputStream,给另外一个程序读取,写成另外一个文件
方案一
程序要写outputStream,程序内部肯定会尝试不断的循环write,直到自己的数据写完。中间可能因为Stream的实现发生线程阻塞。
同理,需要读InputStream的程序,也会循环去读取数据,直到读完位置。中间也可能发生阻塞。
所以同一个线程里面,不存在Piped管道的方案,能够智能的将这个衔接上。
单一线程方案:直接写入到ByteArrayOutputStream中,直接将流写成内存字节数组。再讲数组转到InputStream中
方案二
程序写outputStream和程序读InputStream放入到两个线程中执行。然后用Piped*Stream进行衔接
NIO
Linux的5种IO模型
Java应用到的IO模型
BIO:同步阻塞IO模型
NIO:
Java 1.4 中引入,对应 java.nio 包
提供了 Channel , Selector,Buffer 等抽象
它支持面向缓冲的,基于通道的 I/O 操作方法。 对于高负载、高并发的(网络)应用,应使用 NIO 。
Java 中的 NIO 属于同步非阻塞 IO 模型
模型
升级模型
IO多路复用模型
AIO
AIO 是 Java 1.7 之后引入的包
基于回调实现
JDK 7 引入了Asynchronous I/O,即AIO。在进行I/O编程中,常用的2种模式:Reactor和Proactor。Java的NIO就是Reactor:当有事件触发时,服务器端得到通知,进行相应的处理。
AIO即NIO2.0,叫做异步非阻塞IO。AIO引入异步通道的概念,采用了Proactor模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。
目前AIO还没有广泛应用,Netty也是基于NIO,而不是AIO。
AIO即NIO2.0,叫做异步非阻塞IO。AIO引入异步通道的概念,采用了Proactor模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。
目前AIO还没有广泛应用,Netty也是基于NIO,而不是AIO。
对比
NIO适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4开始支持。Netty基于的是NIO。
AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。AIO暂未得到广泛应用。
AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。AIO暂未得到广泛应用。
参考
https://blog.csdn.net/m0_46517444/article/details/118928565
https://www.cnblogs.com/zackstang/p/14584218.html
对应模型的API
Netty中的IO模型
当前Netty是基于NIO模型
它的异步特征是netty通过自己的线程模型实现的,给work线程提供的异步效果
NIO解放了什么
提高业务线程有效利用率
同时给业务线程提供了异步编程的能力
0 条评论
下一页