一、字节流和字符流的区别
- 字节流是按字节读写,字符流按字符读写
- 字节流默认不使用缓冲区,字符流使用缓冲区
- 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串
- 字符流是字节流的包装
二、字节流和字符流 (记一些 - 了解一下api)
字节流
- 字节输入流
- int read()// 读取并返回1字节数据,若返回-1,表示读到了输入流的末尾。
- int read(byte[] b)// 将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。
- int read(byte[] b, int off, int len)//将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾,off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。
- long skip(long n)// 跳过和丢弃此输入流中数据的n个字节
- void close()// 关闭此输入流并释放与该流关联的所有系统资源。
- 字节输出流
- void write(byte[] b)// 将b.length个字节从指定的byte数组写入此输出流
- void write(byte[] b, int off, int len)// 将指定byte数组中从偏移量off开始的len个字节写入此输出流
- void write(int b)// 将1字节写入此输出流
- void close() // 关闭此输出流并释放与此流有关的所有系统资源
- void flush() // 刷新此输出流并强制写出所有缓冲的输出字节
字符流
- 字符输入流
- int read()// 读取并返回1字符数据,若返回-1,表示读到了输入流的末尾。
- int read(char[] b)// 将数据读入一个字符数组,同时返回实际读取的字符数。如果返回-1,表示读到了输入流的末尾。
- int read(char[] b, int off, int len)//将数据读入一个字符数组,同时返回实际读取的字符数。如果返回-1,表示读到了输入流的末尾,off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字符数。
- long skip(long n)// 跳过和丢弃此输入流中数据的n个字符
- void close()// 关闭此输入流并释放与该流关联的所有系统资源。
- 字符输出流
- void write(char[] b)// 将b.length个字符从指定的byte数组写入此输出流
- void write(char[] b, int off, int len)// 将指定byte数组中从偏移量off开始的len个字符写入此输出流
- void write(int b)// 将1字符写入此输出流。
- void write(String b)// 将字符串写入此输出流
- void close() // 关闭此输出流并释放与此流有关的所有系统资源
- void flush() // 刷新此输出流并强制写出所有缓冲的输出字
三、分类
-
按照流的方向:输入流(inputStream)和输出流(outputStream)
-
按照实现功能分:节点流和拓展流,采用了”装饰器设计模式思想”
节点流才具备真正操作文件的能力,拓展流只是让流的功能更加强大而已,拓展流脱离了节点流的话,那么是不允许的拓展流的使用必须要建立在节点流的基础之上
-
按照处理数据的单位: 字节流和字符流
分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的
四、装饰器模式
定义
- 在不改变对象现有结构的情况下,动态的给对象添加额外的功能
- 相比于继承,装饰器模式能对不支持继承的类进行增强;并且比继承更灵活,不需要生成大量的子类
在装饰器模式中的角色有(理解)
- 抽象构件(Component)角色:给出一个抽象接口,已规范准备接收附加责任的对象。
- 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类
- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
- 具体装饰(ConcreteDecorator)角色:负责给构件对象增加新的责任
优点
- 比继承更灵活。继承是静态的,而且一旦继承所有子类都有一样的功能。而装饰模式采用把功能分离到每个装饰器中,然后通过对象组合的方式,在运行时动态的组合功能,每个被装饰的对象最终有哪些功能,是由运行期动态组合的功能决定的
- 更容易复用功能。有利于装饰器功能的复用,可以给一个对象多次增加同一个装饰器,也可以用同一个装饰器来装饰不同的对象
- 简化高层定义。装饰模式可以通过组合装饰器方式给对象增添任意多的功能,因此在进行高层定义的时候,只需要定义最基本的功能就可以了,需要的时候结合相应装饰器完成需要的功能
缺点
- 多层装饰比较复杂
五、BIO NIO AIO [IO模型]
什么叫对象序列化,什么是反序列化
- 对象序列化:将对象以二进制的形式保存在硬盘上
- 反序列化:将二进制的文件转化为对象,读取实现serializable接口
- 不想让字段放在硬盘上就加transient
通俗理解同步异步、阻塞非阻塞
同步和异步
- 同步和异步指的是一个执行流程中每个方法是否必须依赖前一个方法完成后才可以继续执行。假设我们的执行流程中:依次是方法一和方法二。
- 同步指的是调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。即方法二一定要等到方法一执行完成后才可以执行。
- 异步指的是调用立刻返回,调用者不必等待方法内的代码执行结束,就可以继续后续的行为。(具体方法内的代码交由另外的线程执行完成后,可能会进行回调)。即执行方法一的时候,直接交给其他线程执行,不由主线程执行,也就不会阻塞主线程,所以方法二不必等到方法一完成即可开始执行。
阻塞与非阻塞
- 阻塞与非阻塞指的是单个线程内遇到同步等待时,是否在原地不做任何操作
- 阻塞指的是遇到同步等待后,一直在原地等待同步方法处理完成
- 非阻塞指的是遇到同步等待,不在原地等待,先去做其他的操作,隔断时间再来观察同步方法是否完成
BIO - 传统的IO模型 - 同步阻塞IO
- 同步阻塞,在服务器中实现的模式为一个连接一个线程。线程发起IO请求后,一直阻塞IO,直到缓冲区数据就绪后,再进入下一步操作。BIO一般适用于连接数目小且固定的架构,这种方式对于服务器资源要求比较高,而且并发局限于应用中,是JDK1.4之前的唯一选择,但好在程序直观简单,易理解。
NIO - 同步非阻塞IO
- 同步非阻塞,在服务器中实现的模式为一个线程处理多个请求(连接),同步指的是必须等待IO缓冲区内的数据就绪,而非阻塞指的是,用户线程不原地等待IO缓冲区,可以先做一些其他操作,但是要定时轮询检查IO缓冲区数据是否就绪。NIO一般适用于连接数目多且连接比较短(轻操作)的架构,并发局限于应用中,编程比较复杂,从JDK1.4开始支持。(间隔轮询,不断发送请求,会消耗cpu资源)
AIO - 异步非阻塞IO
- 异步非阻塞,在服务器中实现的模式为一个有效请求一个线程,用户线程只需要告诉内核,当缓冲区就绪后,通知用户线程或者执行用户线程交给内核的回调函数。AIO一般适用于连接数目多且连接比较长(重操作)的架构,充分调用操作系统参与并发操作,编程比较复杂,从JDK1.7开始支持。
理解各种
同步阻塞
:你到饭馆点餐,然后在那等着,还要一边喊:好了没啊!(BIO)同步非阻塞
:在饭馆点完餐,就去遛狗了。不过溜一会儿,就回饭馆喊一声:好了没啊!(NIO)异步阻塞
:遛狗的时候,接到饭馆电话,说饭做好了,让您亲自去拿。异步非阻塞
:饭馆打电话说,我们知道您的位置,一会给你送过来,安心遛狗就可以了。(AIO)
六、BIO和NIO的区别、NIO和AIO的区别(以下可用于回答)
阻塞IO调用 :
- 在用户进程中调用执行的时候,进程会等待该IO操作,而且进程无法执行其他操作
非阻塞IO调用:
- 在用户进程中调用执行的时候,无论成功与否,该IO操作会立即返回,进程可以进行其他操作(当然如果是读取到数据,一般就接着进行数据处理)。
同步IO:
- 用户进程发出IO调用,去获取IO设备数据,双方的数据要经过内核缓冲区同步,完全准备好后,再复制返回到用户进程。整个过程会导致请求进程阻塞,直到I/O操作完成。
异步IO:
- 用户进程发出IO调用,去获取IO设备数据,并不需要同步,内核直接复制到进程,整个过程不会导致请求进程阻塞。
NIO与IO的区别
首先来讲一下传统的IO和NIO的区别,传统的IO又称BIO,即阻塞式IO,NIO就是非阻塞IO了。还有一种AIO就是异步IO,这里不加阐述了。
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。