面试题答案
一键面试Java传统I/O操作流程
- 基于字节流从文件读取数据:
- 创建
FileInputStream
对象,指定要读取的文件路径。 - 通过
read()
方法逐字节读取数据,或使用read(byte[] b)
方法将数据读取到字节数组中。 - 读取完成后,关闭
FileInputStream
。
- 创建
- 基于字符流从文件读取数据:
- 创建
FileReader
对象,指定要读取的文件路径。 - 创建
BufferedReader
对象,将FileReader
作为参数传入,以提高读取效率。 - 使用
readLine()
方法逐行读取数据。 - 读取完成后,关闭
BufferedReader
和FileReader
。
- 创建
- 基于字节流网络通信(客户端):
- 创建
Socket
对象,指定服务器的IP地址和端口号。 - 通过
Socket
的getOutputStream()
获取输出流,getInputStream()
获取输入流。 - 使用输出流向服务器发送数据,使用输入流从服务器接收数据。
- 通信完成后,关闭流和
Socket
。
- 创建
- 基于字节流网络通信(服务器端):
- 创建
ServerSocket
对象,指定监听的端口号。 - 通过
accept()
方法等待客户端连接,返回一个Socket
对象。 - 获取
Socket
的输入输出流,进行数据的读写操作。 - 通信完成后,关闭流和
Socket
,ServerSocket
可选择关闭。
- 创建
Java AIO异步I/O操作流程
- 从文件读取数据:
- 创建
AsynchronousSocketChannel
对象并打开。 - 创建
ByteBuffer
用于存储数据。 - 使用
AsynchronousSocketChannel
的read(ByteBuffer dst)
方法异步读取数据,该方法立即返回,不会阻塞线程。 - 通过
Future<Integer>
或使用回调函数来处理读取结果。读取完成后,关闭AsynchronousSocketChannel
。
- 创建
- 网络通信(客户端):
- 创建
AsynchronousSocketChannel
对象并打开,通过connect(InetSocketAddress remote)
方法异步连接服务器,方法立即返回。 - 使用
Future<Void>
或回调函数处理连接结果。连接成功后,创建ByteBuffer
。 - 使用
AsynchronousSocketChannel
的read(ByteBuffer dst)
和write(ByteBuffer src)
方法进行异步读写操作,同样方法立即返回。 - 通过
Future<Integer>
或回调函数处理读写结果。通信完成后,关闭AsynchronousSocketChannel
。
- 创建
- 网络通信(服务器端):
- 创建
AsynchronousServerSocketChannel
对象并绑定到指定端口。 - 使用
AsynchronousServerSocketChannel
的accept()
方法异步接受客户端连接,方法立即返回。 - 通过
Future<AsynchronousSocketChannel>
或回调函数获取客户端连接的AsynchronousSocketChannel
对象。 - 后续对该
AsynchronousSocketChannel
进行异步读写操作,处理方式与客户端类似。通信完成后,关闭相关AsynchronousSocketChannel
和AsynchronousServerSocketChannel
。
- 创建
关键差异点
- 阻塞方式:
- 传统I/O:是阻塞式的。在进行读写操作时,线程会被阻塞,直到操作完成,这期间线程不能执行其他任务。
- AIO异步I/O:是非阻塞式的。读写操作会立即返回,线程可以继续执行其他任务,通过
Future
或回调函数获取操作结果。
- 性能:
- 传统I/O:在高并发场景下,由于线程阻塞,会导致大量线程资源被占用,性能会受到影响。
- AIO异步I/O:适用于高并发场景,线程不会因I/O操作而阻塞,能更有效地利用系统资源,提高整体性能。
- 编程复杂度:
- 传统I/O:编程模型相对简单直观,易于理解和实现。
- AIO异步I/O:由于涉及异步操作和回调机制,编程复杂度较高,对开发者的要求也更高。