JavaIO流
什么是IO?
IO:指的是输入(input)和输出(output)。
什么是流?
流:指的是一连串的数据(字节或字符),以先进先出的方式发送信息的通道。
当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。
类似的,当程序需要写入数据时,就会开启一个通向目的地的流。
IO流的分类
1.按数据流的方向:输入流和输出流(inputStream和outputStream)
输入和输出是相对于应用程序而言的,比如文件读写,读取文件是输入流,写文件是输出流,不要搞反了
2.按处理数据单位:字节流(inputStream和outputStream)和字符流(write和read)
字节流和字符流的用法几乎完全一样,区别1.在于字节流和字符流所操作的数据单元不同,字节流操作的单元是
8位的字节,而字符流操作的是数据单元是为16位的字符。2.字符流一般用于处理纯文本类型的文件,如TXT文件等,
不能用来处理图像视频等非文本文件。即字节流可以处理一切文件,而字符流只能处理纯文本文件。3.字节流本身没有缓冲区
缓冲字节流相对于字节流,效率提升非常高。而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升不是很大。
3.按功能:节点流和处理流
节点流:直接操作数据读写的流类,比如FileInputStream
处理流:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供强大、灵活的读写功能,比如,BufferInputStream(即缓冲字节流)
处理流和节点流应用了Java的装饰者模式。
缓冲流,也是处理流的一种,能够减少程序与磁盘之间的交互,是提升程序效率的一种有效手段。
思路:缓冲流在内存中设置一个缓冲区,缓冲区先存储足够的待操作数据后,再与内存或磁盘进行交互。
这样的话,在总数据量不变的情况下,通过提高每次交互的数据量,减少了交互次数。
注意:缓冲流效率一定高吗?在某些情形下,缓冲流效率反而更低。
FIle类是用来操作文件的类,但他不能操作文件中的数据,他实现了Serializable、Comparable<File>,说明他是支持序列化和排序的。
字节流:InputStream和OutputStream是两个抽象类,是字节流的基类,所有的具体字节流实现类都是继承了这两个类。
字符流:Writer和Reader是两个抽象类,其它的字符流实现类都是继承了这两个类。
Java序列化(Serialization)和反序列化(DeSerialization)
序列化:把对象转化为字节序列的过程称为对象的序列化。
为什么要序列化:我们需要把数据保存到磁盘即持久化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化
ObjectOutputStream表示对象输出流,它的writeObject()方法从可以对参数指定的object对象进行序列化,把得到的字节序列写到一个目标输出流中。
ObjectInputStream()方法从源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
注意:1.序列化时,只对对象的状态进行 保存,而不管对象的方法。
2.当一个父类实现序列化,子类自动实现序列化,不需要显示实现Serialization接口
3.当一个对象的实例变量引用其它对象,序列化该对象时,也把引用对象进行序列化
4.并非所有的对象都可以序列化,比如:声明为static(代表类的状态)和transient(代表对象的临时数据)类型的数据不能被序列化。
BIO(blocking IO):即同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求使时务器就需要启动一个线程进行处理,
如果这个连接不做任何事情会造成不必要的线程开销。
NIO(non-blocking IO):即同步非阻塞,服务器
NIO三大核心部分:Channel(通道),Buffer(缓冲区),Selector(选择器)
NIO是面向缓冲区的,或者面向块编程的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区内前后,这就增加了处理过程中的灵活性,使用它可以提供非阻塞的高伸缩性网络。
Java NIO的非阻塞模式,使一个线程从某通道发送或者读取数据,但它仅能得到目前可用的数据,如果目前没有可用的数据时,就什么都不会获取,而不是保持线程阻塞,
所以直至数据变的可读取之前,该线程可以继续做其他的事情。非阻塞就是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
BIO和NIO的区别
1.BIO以流的方式处理数据,NIO以块的方式处理数据,块的效率比流的效率高很多。
2.BIO是阻塞的,NIO是非阻塞的。
3.BIO基于字节流和字符流进行操作的,而NIO基于Channel和Buffer进行操作的,数据总是从通道读取到缓冲区中,或者从缓冲区写入到
通道中。Selector用于监听多个通道事件,因此使用单个线程就可以监听多个客户端通道。
IO多路复用
先了解最基本的Socket模型
想要客户端和服务器能在网络中同信,那必须得使Socket编程,它是进程间通信里比较特别的方式---->他可以跨主机间通信。
Socket的中文名叫作插口,客户端和服务器在进行网络通信前,各自得创建一个Socket,这相当于客户端和服务器打开了一个
“口子”。就像手机充电一样,得用一根数据线,一头插在手机充电口,一头插在插座上,然后进行充电。
如果每次都为客户端分配一个进程/线程来处理请求,那就意味着一万个请求是不是要分配一万个进程/线程???
所以有没有一种可能,我们只使用一个进程来维护多个Socket???当然是有的,————IO多路复用技术。
一个进程虽然任意时刻只能处理一个请求,但是处理每个请求,但是每个请求的事件时,耗时可以控制在1毫秒以内,这样
1秒内就可以处理上千个请求,把时间拉长来看,多个请求复用了一个线程,这就是多路复用,类似于一个CPU并发处理多个线程,所以也叫时分多路复用。