JAVA-IO流

JAVA基础之IO流

1.同步与异步,阻塞与非阻塞

●同步:方法1调用方法2,方法1必须等到方法2返回后,才能继续进行。

●异步:方法1调用方法2后,当方法2完成的时候会主动通知方法1

●阻塞:当前进程发送一个请求后,直接挂起,直到请求回复后才继续工作。

●非阻塞:发送请求后,不用一直等待结果,可以先去干别的事,每隔一段时间检查下是否返回。(和异步差不多嘛)

●同步阻塞:方法1调用方法2后,就一直等着方法2完成,完成后,再继续干别的

●异步阻塞:方法1调用方法2后,虽然方法2会主动告诉方法1何时完成了,但是由于是阻塞的,方法1还是一直在等着。

●同步非阻塞:方法1调用方法2后,去做别的了,过一段时间主动看一下方法2是否完成。

●异步非阻塞:方法1调用方法2后,去做别的了,方法2完成后会主动告诉方法1,我完成了。

2.BIO(Blocking I/O)

●同步阻塞I/O:线程发起IO请求后,一直阻塞,直到数据读/写完成后,再进行下一步操作。如果要同时处理多个请求,必须使用多线程,开销大。内核将数据准备好之前,系统调用会一直等待所有的套接字,默认是BIO

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yhkFd8ES-1650425898086)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/109.png)]

3.NIO(NoBlockingI/O)

●同步非阻塞I/O模型:线程发起IO请求后,立即返回,去做别的事,但是需要定时过来检查一下数据是否读写完成。偶尔看一眼,如果有IO请求了,就进行处理,其他时间干别的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DNVc0j01-1650425898087)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/110.png)]

4.AIO(asynchronous I/O)

●异步非阻塞I/O模型:基于回调机制实现,线程发起IO请求后立即返回(非阻塞),当数据读写完成后,操作系统会通知线程进行后续操作(异步)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cjbx2uCp-1650425898088)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/111.png)]

5.IO流分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nyo8YqcR-1650425898088)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/112.png)]

●按处理数据单位分类

​ ■字符流:以字符为单位,每次读入或读出16位的数据,只能读取字符类型数据(Java代码接受数据类型一般为char数组)

​ ■字节流:以字节为单位,每次读入或读出8位数据。可以读任何类型的数据,图片,文字,视频(Java代码接受数据类型为byte数组),为什么各种文件都是以字节流读取呀,------这个看电脑文件属性即可,CPU规定计算机存储文件单位以字节来计算。

●按流的方向:

​ ■输入流:从文件读入到内存,只能进行读操作

​ ■输出流:从内存读出到文件,只能进行写操作,可以帮助我们创建文件。

●按是否直接与硬盘、内存等连接:

​ ■节点流:直接与数据源相连,读入或读出

​ ■处理流:对已存在的流进行包装,通过所封装的流的功能实现调用数据读写。如添加个Buffering缓冲区。

6.比特(Bit)、字节(Byte)、字符(char)

●Bit是最小的二进制单位,取值0/1,计算机只认识这个

●Byte计算机最小存储单位,是一个8位的二进制数(1Byte = 8Bit,取值-128到127)

●Char是用户可读的最小单位(Java里 char = 16bit = 2Byte)

7.JavaIO流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9X1TZywT-1650425898089)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/113.png)]

●抽象基类:InputStream、OutputStream(字节流)、Reader、Writer(字符流)所有流都是从这四个抽象基类派生出来的。

●FileReader(字符流)

​ ■ int read();返回读入的第一个字符。如果到达文件末尾,返回-1(因为读的是整形,所以用强转(char)给转化过来)

​ ■ close();流的关闭,所有流操作后都要关闭,因为物理连接,jvm无法自动关闭。

​ ■ int read(char [] a);将文件中的内容写到了数组中(每次读入个数由数组长度决定最大值)。并且返回值为读入的字符的个数,当为-1表示读完了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yqXTND5q-1650425898090)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/114.png)]

●FileWriter(字符流)

​ ■ 使用构造器FileWriter(file,false)/FileWriter(file)则覆盖掉原来内容

​ ■ 使用FileWriter(file,true)则在原有文件基础上追加

​ ■write(String str);写入字符串str

​ ■write(char [],int x, int y);写入字符数组从x到y的数据。

●BufferedReader(字符流)

​ ■BufferedReader(FileReader)

​ ■readLine():单行读取,读取为空返回null,效果同reader,只是进行了封装,加入了缓冲功能,避免频繁读写硬盘。

●BufferedWriter(字符流)

​ ■BufferedWriter(FileWriter);

​ ■write(String str);增加了缓冲功能,避免频繁读写硬盘。

●FileInputStream(字节流)

​ ■ int read():返回读入的第一个字符。如果到达文件末尾,返回-1(因为读的是整形,所以用强转(byte)转回来)

​ ■ int read(byte [] a);将文件中的内容写到数组中(每次读入个数由数组长度决定最大值)。并且返回值为读入的字符的个数,当为-1时表示读完了。

●FileOutputStream(字节流)

​ ■write(byte [],int x,int y);写入字符数组中从x到y的数据。

●BufferedInputStream(带缓冲区字节输入流)

​ ■BufferedInputStream(InputStream)

​ ■int read(byte[] a);将a文件中的内容写到数组中,(每次读入个数由数组长度决定最大值),并且返回值为读入的字节长度,-1表示读完了;数组越大交互次数越少,但是内存消耗巨大,一般为1024

●BufferedOutputStream(带缓冲区字节输出流):避免每次都和硬盘交互,提高访问效率

​ ■BufferedOutputStream(OutputStream);

​ ■write(byte[],int x,int y);

●注:关闭的时候先关外层的缓冲流,内部的流会自动关闭

●为什么提高效率:内部提供了一个缓存器,长度8192,超过这个长度,输入流内部提供方法flush自动刷新缓冲区。

●标准输入流:System.in(键盘,默认)是inputStream的类型

●标准输出流:System.out(控制台,默认)是PrintStream类型的(OutputStream的子类)

8.网络IO

●BIO编程的问题:BIO是阻塞的,如果多个客户端访问会出现堵塞的问题(第一个客户端等待请求的过程中,其他用户也要陪着等,->同步,第一个用户也没法干别的->阻塞),非常浪费资源。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mfZ2vL89-1650425898091)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/115.png)]

●使用多线程解决BIO阻塞问题:使用多线程确实可以解决堵塞等待时间长的问题,因为其可以充分发挥CPU,但是系统资源是有限的啊,而且多个线程之间切换上下文,也会带来很大的性能消耗。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ARM0dbVf-1650425898092)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/116.png)]

●使用线程池解决线程过多的问题:线程池固然可以解决这个问题,当需求量大的时候也可以扩充线程池,但是如果Socket上来就去创建线程抢占CPU资源,所有的线程都去IO了,CPU利用率也很低。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rNCiB4Kq-1650425898093)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/117.png)]

●使用NIO实现网络通信(JDK官方答案,JDK1.4时出现):客户端的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时候才启动一个线程进行处理。NIO方式适用于连接数目多且连接比较短的架构(redis就是这个)重要组件为:

​ ■通道:也叫多路复用器,是一个对象,可以通过它读取或写入数据。通常都是将数据写入包含一个或多个字节的缓冲区,然后再将缓冲区的数据写入通道,将数据从通道读入缓冲区,再从缓冲区获取数据。类似于IO中的流,不过流是单向的,通道是双向的,可读可写。流是阻塞的,通道可以异步读写。

​ ■选择器:每次客户端来了以后,就会把通道注册到选择器中,并给他一个状态。用死循环来循环判断(判断是否完成某个操作,完成某个操作后改为不一样的状态)状态是否发生了变化,变化了即IO完成,退出死循环。

​ ■缓冲区:和Buffer原理相同,底层为一个数组,内部维护几个状态变量,可以在一块缓冲区上反复读写。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WqCUqUuF-1650425898094)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/118.png)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值