IO 流⾯试题总结

90 阅读6分钟

Q1 :同步/异步/阻塞/⾮阻塞IO的区别?

同步和异步是通信机制,阻塞和⾮阻塞是调⽤状态。\

同步 IO 是⽤户线程发起 IO 请求后需要等待或轮询内核 IO 操作完成后才能继续执⾏。异步 IO 是⽤户线程发起 IO 请求后可以继续执⾏,当内核 IO 操作完成后会通知⽤户线程,或调⽤⽤户线程注册的回调函数。

阻塞 IO 是 IO 操作需要彻底完成后才能返回⽤户空间 。⾮阻塞 IO 是 IO 操作调⽤后⽴即返回⼀个状态值,⽆需等 IO 操作彻底完成。\

Q2 :什么是 BIO

BIO ****是同步阻塞式 IO,JDK1.4 之前的 IO 模型。服务器实现模式为⼀个连接请求对应⼀个线程,服务器需要为每⼀个客户端]请求创建⼀个线程,如果这个连接不做任何事会造成不必要的线程开销。可以通过       线程池改善,这种 IO 称为伪异步 IO。适⽤连接数⽬少且服务器资源多的场景。\

Q3 :什么是 NIO

NIO ****是 JDK1.4 引⼊的同步⾮阻塞 IO。服务器实现模式为多个连接请求对应⼀个线程,客户端连接请求会注册到⼀个多路复⽤器 Selector ,Selector 轮询到连接有 IO 请求时才启动⼀个线程处理。适⽤连接数⽬多且连接时间短的场景。

同步是指线程还是要不断接收客户端连接并处理数据,⾮阻塞是指如果⼀个管道没有数据,不需要等       待,可以轮询下⼀个管道。

核⼼组件:

Selector 多路复⽤器,轮询检查多个 Channel 的状态,判断注册事件是否发⽣,即判断

Channel 是否处于可读或可写状态。使⽤前需要将 Channel 注册到 Selector,注册后会得到⼀个SelectionKey,通过 SelectionKey 获取 Channel 和 Selector 相关信息。

Channel 双向通道,替换了 BIO 中的 Stream 流,不能直接访问数据,要通过 Buffer 来读写数据,也可以和其他 Channel 交互。

Bu er 缓冲区,本质是⼀块可读写数据的内存,⽤来简化数据读写。Buffer 三个重要属性:

position 下次读写数据的位置,limit 本次读写的极限位置,capacity 最⼤容量。

flip 将写转为读,底层实现原理把 position 置 0,并把 limit 设为当前的 position 值。将读转为写模式(⽤于读完全部数据的情况,把 position 置 0,limit 设为

capacity)。

将读转为写模式(⽤于存在未读数据的情况,让 position 指向未读数据的下⼀

个)。

通道⽅向和 Buffer ⽅向相反,读数据相当于向 Buffer 写,写数据相当于从 Buffer 读。

使⽤步骤:向 Buffer 写数据,调⽤ flip ⽅法转为读模式,从 Buffer 中读数据,调⽤ clear 或

compact ⽅法清空缓冲区。

Q4 :什么是 AIO

AIO 是 JDK7 引⼊的异步⾮阻塞 IO。服务器实现模式为⼀个有效请求对应⼀个线程,客户端的 IO 请求都是由操作系统先完成 IO 操作后再通知服务器应⽤来直接使⽤准备好的数据。适⽤连接数⽬多且连接时间⻓的场景。

异步是指服务端线程接收到客户端管道后就交给底层处理IO通信,⾃⼰可以做其他事情,⾮阻塞是指客       户端有数据才会处理,处理好再通知服务器。

实现⽅式包括通过 Future 的成功的回调⽅法

⽅法进⾏阻塞式调⽤以及实现 CompletionHandler 接⼝,重写请求和请求失败回调⽅法 failed 。

Q5 java.io 包下有哪些流?

主要分为字符流和字节流,字符流⼀般⽤于⽂本⽂件,字节流⼀般⽤于图像或其他⽂件。

字符流包括了字符输⼊流 Reader 和字符输出流 Writer,字节流包括了字节输⼊流 InputStream 和字节输出流 OutputStream。字符流和字节流都有对应的缓冲流,字节流也可以包装为字符流,缓冲流带有

⼀个 8KB 的缓冲数组,可以提⾼流的读写效率。除了缓冲流外还有过滤流 FilterReader、字符数组流

CharArrayReader、字节数组流 ByteArrayInputStream、⽂件流 FileInputStream 等。

Q6 :序列化和反序列化是什么?

Java 对象 JVM 退出时会全部销毁,如果需要将对象及状态持久化,就要通过序列化实现,将内存中的对象保存在⼆进制流中,需要时再将⼆进制流反序列化为对象。对象序列化保存的是对象的状态,因此       属于类属性的静态变量不会被序列化。

常⻅的序列化有三种:

**Java **原⽣序列化

实现 标记接⼝,Java 序列化保留了对象类的元数据(如类、成员变量、继承类

信息)以及对象数据,兼容性最好,但不⽀持跨语⾔,性能⼀般。序列化和反序列化必须保持序列

化 ID 的⼀致,⼀般使⽤ 定义序列化 ID,

如果不设置编译器会根据类的内部实现⾃动⽣成该值。如果是兼容升级不应该修改序列化        ID,防

⽌出错,如果是不兼容升级则需要修改。

Hessian 序列化

Hessian  序列化是⼀种⽀持动态类型、跨语⾔、基于对象传输的⽹络协议。Java  对象序列化的⼆进制流可以被其它语⾔反序列化。Hessian 协议的特性:① ⾃描述序列化类型,不依赖外部描述⽂件,⽤⼀个字节表示常⽤基础类型,极⼤缩短⼆进制流。② 语⾔⽆关,⽀持脚本语⾔。③ 协议简单,⽐ Java 原⽣序列化⾼效。Hessian 会把复杂对象所有属性存储在⼀个 Map 中序列化,当⽗类和⼦类存在同名成员变量时会先序列化⼦类再序列化⽗类,因此⼦类值会被⽗类覆盖。

JSON 序列化

JSON 序列化就是将数据对象转换为 JSON 字符串,在序列化过程中抛弃了类型信息,所以反序列化时只有提供类型信息才能准确进⾏。相⽐前两种⽅式可读性更好,⽅便调试。

序列化通常会使⽤⽹络传输对象,⽽对象中往往有敏感数据,容易遭受攻击,Jackson 和 fastjson 等都出现过反序列化漏洞,因此不需要进⾏序列化的敏感属性传输时应加上 transient 关键字。transient 的作⽤就是把变量⽣命周期仅限于内存⽽不会写到磁盘⾥持久化,变量会被设为对应数据类型的零值。

 最后呢,本文章的所有知识取自于B站高淇老师讲的Java300集教程,里面更加全面的讲述了关于Java面试中所能遇到的各种问题,包括解决问题的方法。小编也给大家准备了充分的资源:

给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibili