2025 Java NIO 面试题 (精选90题) 1~30
1. 什么是Java NIO?
Java NIO(New Input/Output)是Java 1.4引入的一套新的I/O API,提供了与标准Java I/O不同的I/O处理方式。它支持面向缓冲区的、基于通道的I/O操作,提供了更高的性能和更灵活的I/O操作方式。
2. Java NIO与传统的IO有什么区别?
- 面向流 vs 面向缓冲区:传统IO是面向流的,而NIO是面向缓冲区的。
- 阻塞 vs 非阻塞:传统IO是阻塞的,而NIO支持非阻塞模式。
- 选择器:NIO引入了选择器(Selector),允许一个线程处理多个通道,提高了并发性能。
3. Java NIO的核心组件有哪些?
Java NIO的核心组件包括:
- 通道(Channel):用于数据的读写。
- 缓冲区(Buffer):用于存储数据。
- 选择器(Selector):用于多路复用,允许一个线程处理多个通道。
4. 什么是通道(Channel)?
通道(Channel)是Java NIO中的一个抽象类,用于数据的读写操作。它类似于流,但支持双向读写,并且可以与缓冲区配合使用。常见的通道实现包括FileChannel、SocketChannel、ServerSocketChannel和DatagramChannel。
5. 什么是缓冲区(Buffer)?
缓冲区(Buffer)是Java NIO中用于存储数据的容器。它是一个线性、有限的数据集合,可以存储各种数据类型(如字节、字符、整数等)。缓冲区的主要属性包括容量(Capacity)、位置(Position)、限制(Limit)和标记(Mark)。
6. 什么是选择器(Selector)?
选择器(Selector)是Java NIO中的一个类,用于实现多路复用I/O。它允许一个线程监控多个通道的I/O事件(如读、写、连接等),从而在一个线程中处理多个通道的I/O操作,提高了并发性能。
7. 缓冲区(Buffer)的基本属性有哪些?
缓冲区(Buffer)的基本属性包括:
- 容量(Capacity):缓冲区可以存储的最大数据量。
- 位置(Position):当前读写操作的位置。
- 限制(Limit):缓冲区中可以读写的数据的上限。
- 标记(Mark):一个备忘位置,可以通过reset()方法回到这个位置。
8. Buffer的容量(Capacity)、位置(Position)、限制(Limit)和标记(Mark)分别是什么?
- 容量(Capacity):缓冲区可以存储的最大数据量,一旦创建,容量不可改变。
- 位置(Position):当前读写操作的位置,每次读写操作后,位置会自动增加。
- 限制(Limit):缓冲区中可以读写的数据的上限,不能超过容量。
- 标记(Mark):一个备忘位置,可以通过mark()方法设置,通过reset()方法回到这个位置。
9. 如何创建一个Buffer?
可以通过Buffer的静态方法创建不同类型的缓冲区,例如:
// 创建一个容量为1024字节的字节缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 创建一个容量为1024字符的字符缓冲区
CharBuffer charBuffer = CharBuffer.allocate(1024);
10. Buffer有哪些类型?
Java NIO提供了多种类型的缓冲区,包括:
- ByteBuffer:用于存储字节数据。
- CharBuffer:用于存储字符数据。
- ShortBuffer:用于存储短整型数据。
- IntBuffer:用于存储整型数据。
- LongBuffer:用于存储长整型数据。
- FloatBuffer:用于存储浮点型数据。
- DoubleBuffer:用于存储双精度浮点型数据。
11. 什么是直接缓冲区(Direct Buffer)和非直接缓冲区(Non-direct Buffer)?
- 直接缓冲区(Direct Buffer):直接在JVM堆外分配内存空间,通过本地I/O操作直接与操作系统交互,减少了数据在JVM堆与操作系统之间的拷贝,适合高频、大数据量的I/O操作,但创建和销毁成本较高。
- 非直接缓冲区(Non-direct Buffer):在JVM堆中分配内存,数据需要通过JVM堆与操作系统之间的拷贝进行I/O操作,适合小数据量或低频操作,创建和销毁成本低。
12. 直接缓冲区与非直接缓冲区的区别是什么?
- 内存分配位置:直接缓冲区在JVM堆外分配,非直接缓冲区在JVM堆内分配。
- 性能:直接缓冲区减少数据拷贝,适合高频I/O;非直接缓冲区需要数据拷贝,适合低频I/O。
- 生命周期管理:直接缓冲区由JVM通过本地方法管理,非直接缓冲区由JVM垃圾回收器管理。
- 适用场景:直接缓冲区适合大文件或网络传输;非直接缓冲区适合小数据操作。
13. 如何将数据写入Buffer?
通过put()
方法将数据写入Buffer,例如:
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put((byte)1); // 写入一个字节
buffer.put(new byte[]{1, 2, 3}); // 写入字节数组
14. 如何从Buffer读取数据?
通过get()
方法从Buffer读取数据,例如:
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put((byte)1);
buffer.flip(); // 切换为读模式
byte b = buffer.get(); // 读取一个字节
byte[] dst = new byte[3];
buffer.get(dst); // 读取字节数组
15. 什么是Buffer的翻转(flip)操作?
flip()
方法将Buffer从写模式切换为读模式,具体操作:
- 将
limit
设置为当前position
。 - 将
position
重置为0。
用于准备从Buffer中读取数据。
16. 什么是Buffer的清除(clear)操作?
clear()
方法清空Buffer,准备写入数据,具体操作:
- 将
position
重置为0。 - 将
limit
设置为capacity
。
注意:clear()
不会清空数据,只是重置指针。
17. 什么是Buffer的重绕(rewind)操作?
rewind()
方法将position
重置为0,mark
被丢弃,用于重新读取Buffer中的数据。
18. 什么是Buffer的压缩(compact)操作?
compact()
方法将未读的数据移动到Buffer的开头,并将position
设置为未读数据的末尾,limit
设置为capacity
,用于保留未读数据并准备写入新数据。
19. 什么是Channel的基本概念?
Channel是Java NIO中用于数据传输的抽象,类似于流,但支持双向读写,可以与Buffer配合使用。Channel是双向的,可以从Channel读取数据到Buffer,也可以从Buffer写入数据到Channel。
20. Channel与Stream的区别是什么?
- 方向性:Stream是单向的(输入流或输出流),Channel是双向的。
- 缓冲区:Stream直接操作数据,Channel需要通过Buffer操作数据。
- 阻塞模式:Stream默认是阻塞的,Channel支持非阻塞模式。
21. Channel有哪些类型?
常见的Channel类型包括:
- FileChannel:用于文件I/O。
- SocketChannel:用于TCP网络通信。
- ServerSocketChannel:用于监听TCP连接。
- DatagramChannel:用于UDP网络通信。
22. 如何创建一个FileChannel?
通过FileInputStream
、FileOutputStream
或RandomAccessFile
获取FileChannel:
FileChannel channel = new FileInputStream("file.txt").getChannel();
23. 如何使用FileChannel读取文件?
FileChannel channel = new FileInputStream("file.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer); // 读取数据到Buffer
buffer.flip(); // 切换为读模式
// 处理Buffer中的数据
channel.close();
24. 如何使用FileChannel写入文件?
FileChannel channel = new FileOutputStream("file.txt").getChannel();
ByteBuffer buffer = ByteBuffer.wrap("Hello".getBytes());
channel.write(buffer); // 写入数据到文件
channel.close();
25. 什么是SocketChannel?
SocketChannel是Java NIO中用于TCP网络通信的Channel,支持非阻塞模式,可以通过SocketChannel.open()
创建或通过ServerSocketChannel.accept()
接受连接。
26. 如何创建一个SocketChannel?
SocketChannel channel = SocketChannel.open();
channel.connect(new InetSocketAddress("localhost", 8080));
27. 如何使用SocketChannel进行网络通信?
SocketChannel channel = SocketChannel.open();
channel.connect(new InetSocketAddress("localhost", 8080));
ByteBuffer buffer = ByteBuffer.wrap("Hello".getBytes());
channel.write(buffer); // 发送数据
buffer.clear();
channel.read(buffer); // 接收数据
buffer.flip();
// 处理接收到的数据
channel.close();
28. 什么是ServerSocketChannel?
ServerSocketChannel是Java NIO中用于监听TCP连接的Channel,支持非阻塞模式,通过ServerSocketChannel.open()
创建,并调用bind()
绑定端口。
29. 如何创建一个ServerSocketChannel?
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
30. 如何使用ServerSocketChannel接受客户端连接?
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
SocketChannel clientChannel = serverChannel.accept(); // 阻塞等待客户端连接
// 处理客户端连接
clientChannel.close();
serverChannel.close();
2025 Java NIO 面试题 (精选90题) 31~60
31. 什么是Java NIO的文件锁(FileLock)?
Java NIO的文件锁(FileLock)是一种机制,用于控制多个进程或线程对同一文件的并发访问。文件锁可以防止多个进程同时修改同一个文件,从而避免数据不一致的问题。
32. 文件锁的作用是什么?
文件锁的主要作用是提供对文件的互斥访问,确保在同一时间只有一个进程或线程可以对文件的特定部分进行读写操作,从而保证数据的完整性和一致性。
33. 如何使用FileChannel获取文件锁?
可以通过FileChannel的tryLock()
或lock()
方法获取文件锁:
FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.WRITE);
FileLock lock = channel.tryLock(); // 尝试获取锁
if (lock != null) {
// 操作文件
lock.release(); // 释放锁
}
channel.close();
34. 文件锁有哪些类型?
文件锁分为两种类型:
- 共享锁(Shared Lock):多个进程可以同时持有共享锁,用于只读操作。
- 排他锁(Exclusive Lock):同一时间只能有一个进程持有排他锁,用于读写操作。
35. 什么是内存映射文件(Memory-mapped File)?
内存映射文件(Memory-mapped File)是一种将文件直接映射到内存的技术,通过将文件映射到虚拟内存空间,可以直接通过内存操作来读写文件,从而提高I/O性能。
36. 内存映射文件的作用是什么?
内存映射文件的主要作用是提高大文件的读写性能,减少用户空间和内核空间之间的数据拷贝,适用于需要频繁访问大文件的场景。
37. 如何使用FileChannel创建内存映射文件?
可以通过FileChannel的map()
方法创建内存映射文件:
FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.READ);
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
// 通过buffer访问文件内容
channel.close();
38. 内存映射文件的性能优势是什么?
内存映射文件的性能优势包括:
- 减少数据拷贝:直接通过内存访问文件,避免用户空间和内核空间之间的数据拷贝。
- 提高访问速度:利用操作系统的页面缓存机制,提高文件的读写速度。
- 适合大文件:可以分段映射大文件,避免一次性加载整个文件到内存。
39. 什么是Java NIO的管道(Pipe)?
Java NIO的管道(Pipe)是一种用于线程间单向数据传输的机制,由SourceChannel
和SinkChannel
组成,数据只能从SinkChannel
写入,从SourceChannel
读取。
40. 管道的作用是什么?
管道的主要作用是实现线程间的单向数据通信,适用于生产者-消费者模式或其他需要线程间数据传递的场景。
41. 如何创建一个Pipe?
可以通过Pipe.open()
方法创建管道:
Pipe pipe = Pipe.open();
Pipe.SinkChannel sinkChannel = pipe.sink(); // 写入通道
Pipe.SourceChannel sourceChannel = pipe.source(); // 读取通道
42. 如何使用Pipe进行线程间通信?
Pipe pipe = Pipe.open();
Pipe.SinkChannel sinkChannel = pipe.sink();
Pipe.SourceChannel sourceChannel = pipe.source();
// 线程1:写入数据
new Thread(() -> {
ByteBuffer buffer = ByteBuffer.wrap("Hello".getBytes());
sinkChannel.write(buffer);
}).start();
// 线程2:读取数据
new Thread(() -> {
ByteBuffer buffer = ByteBuffer.allocate(1024);
sourceChannel.read(buffer);
buffer.flip();
// 处理读取到的数据
}).start();
43. Java NIO与传统IO在性能上的区别是什么?
- NIO:基于缓冲区和通道,支持非阻塞I/O和多路复用,适合高并发、大数据量的场景。
- 传统IO:基于流,阻塞式I/O,适合低并发、小数据量的场景。
44. Java NIO适用于哪些场景?
- 高并发网络通信(如聊天服务器)。
- 大文件读写(如视频处理)。
- 需要非阻塞I/O的场景。
45. 传统IO适用于哪些场景?
- 低并发、小数据量的文件操作。
- 简单的输入输出需求。
- 不需要非阻塞I/O的场景。
46. Java NIO的缺点是什么?
- 编程复杂度较高,需要理解缓冲区、通道等概念。
- 调试难度较大。
- 对小数据量的操作性能提升不明显。
47. 什么是Java NIO的零拷贝(Zero-copy)技术?
零拷贝技术是一种减少数据在内存中拷贝次数的技术,通过直接将数据从文件或网络传输到目标缓冲区,避免了内核空间和用户空间之间的数据拷贝。
48. 零拷贝技术的作用是什么?
零拷贝技术的主要作用是提高数据传输效率,减少CPU和内存的开销,适用于大文件传输或网络通信场景。
49. 如何使用Java NIO实现零拷贝?
可以通过FileChannel
的transferTo()
或transferFrom()
方法实现零拷贝:
FileChannel sourceChannel = new FileInputStream("source.txt").getChannel();
FileChannel targetChannel = new FileOutputStream("target.txt").getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);
50. 什么是Java NIO的Scatter/Gather?
Scatter/Gather是一种分散读和集中写的I/O操作方式:
- Scatter:将数据从Channel分散读取到多个Buffer中。
- Gather:将多个Buffer中的数据集中写入到Channel中。
51. Scatter/Gather的作用是什么?
Scatter/Gather的作用是提高I/O操作的灵活性,适用于需要将数据分散到多个缓冲区或从多个缓冲区集中写入的场景。
52. 如何使用Scatter/Gather进行IO操作?
FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.READ);
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] buffers = {header, body};
channel.read(buffers); // Scatter读取
// 处理数据后写入
channel.write(buffers); // Gather写入
53. Java NIO的字符集(Charset)是什么?
字符集(Charset)是Java NIO中用于字符编码和解码的机制,定义了字符与字节之间的映射关系。
54. 字符集的作用是什么?
字符集的主要作用是实现文本数据的编码和解码,确保不同平台或系统之间的文本数据能够正确传输和显示。
55. 如何使用Charset进行字符编码和解码?
Charset charset = Charset.forName("UTF-8");
ByteBuffer byteBuffer = charset.encode("Hello"); // 编码
CharBuffer charBuffer = charset.decode(byteBuffer); // 解码
56. Java NIO的Charset有哪些常见的实现?
常见的Charset实现包括:
- UTF-8:支持多语言的变长编码。
- ISO-8859-1:单字节编码,适用于西欧语言。
- GBK:中文编码。
57. 什么是Java NIO的Path?
Path是Java NIO中用于表示文件系统路径的接口,替代了传统的File
类,提供了更丰富的路径操作方法。
58. Path的作用是什么?
Path的主要作用是表示和操作文件系统路径,支持路径的拼接、解析、规范化等操作。
59. 如何使用Path进行文件操作?
Path path = Paths.get("file.txt");
Files.readAllBytes(path); // 读取文件
Files.write(path, "Hello".getBytes()); // 写入文件
60. Java NIO的Files类有哪些常用方法?
Files类的常用方法包括:
readAllBytes(Path)
:读取文件所有字节。write(Path, byte[])
:写入字节到文件。copy(Path, Path)
:复制文件。delete(Path)
:删除文件。exists(Path)
:检查文件是否存在。
2025 Java NIO 面试题 (精选90题) 61~90
61. 什么是Java NIO的零拷贝(Zero-copy)技术?
Java NIO的零拷贝技术是一种优化数据传输的方式,它允许数据直接在内存和I/O设备之间传输,而无需经过应用程序缓冲区的多次拷贝。这种技术可以显著提高数据传输效率,减少CPU和内存的开销。
62. 零拷贝技术的作用是什么?
零拷贝技术的主要作用是减少数据在内存中的拷贝次数,从而提高数据传输速度,降低CPU使用率,并减少内存带宽的占用。它特别适用于大文件传输和网络通信等需要高效数据传输的场景。
63. 如何使用Java NIO实现零拷贝?
在Java NIO中,可以通过FileChannel
的transferTo()
和transferFrom()
方法实现零拷贝。例如,将一个文件的内容直接传输到另一个文件或网络通道:
FileChannel sourceChannel = new FileInputStream("source.txt").getChannel();
FileChannel targetChannel = new FileOutputStream("target.txt").getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);
64. 什么是Java NIO的Scatter/Gather?
Scatter/Gather是Java NIO中的一种I/O操作方式,允许数据分散地从多个缓冲区读取(Scatter)或集中地写入到多个缓冲区(Gather)。这种方式可以提高数据处理的灵活性和效率。
65. Scatter/Gather的作用是什么?
Scatter/Gather的作用是简化复杂的数据处理流程,特别是在需要将数据分散到多个缓冲区或从多个缓冲区集中读取的场景中。它可以提高数据传输的效率,并减少编程复杂性。
66. 如何使用Scatter/Gather进行IO操作?
使用FileChannel
的read()
和write()
方法,传入一个ByteBuffer
数组即可实现Scatter/Gather操作。例如:
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] buffers = {header, body};
fileChannel.read(buffers); // Scatter读取
// 处理数据后
fileChannel.write(buffers); // Gather写入
67. Java NIO的字符集(Charset)是什么?
Java NIO的字符集(Charset)是用于字符编码和解码的机制,它定义了字符与字节之间的映射关系。字符集确保了文本数据在不同系统和平台之间的正确传输和显示。
68. 字符集的作用是什么?
字符集的主要作用是实现文本数据的编码和解码,支持多种字符编码标准(如UTF-8、ISO-8859-1等),确保文本数据在不同环境中的兼容性和一致性。
69. 如何使用Charset进行字符编码和解码?
使用Charset
类的encode()
和decode()
方法可以进行字符编码和解码。例如:
Charset charset = Charset.forName("UTF-8");
ByteBuffer byteBuffer = charset.encode("你好"); // 编码为字节
CharBuffer charBuffer = charset.decode(byteBuffer); // 解码为字符
70. Java NIO的Charset有哪些常见的实现?
常见的字符集实现包括:
- UTF-8:支持全球所有语言的变长编码,广泛使用。
- ISO-8859-1:单字节编码,主要用于西欧语言。
- GBK:中文编码标准,支持简体中文。
71. 什么是Java NIO的Path?
Java NIO的Path
接口是用于表示文件系统路径的抽象,它提供了比传统File
类更丰富的路径操作功能,如路径拼接、解析、规范化等。
72. Path的作用是什么?
Path
的作用是提供一种更现代、更灵活的方式来处理文件系统路径,支持跨平台操作,并简化了路径操作的代码编写。
73. 如何使用Path进行文件操作?
通过Files
工具类结合Path
可以方便地进行文件操作,例如:
Path path = Paths.get("example.txt");
Files.createFile(path); // 创建文件
Files.write(path, "Hello".getBytes()); // 写入内容
List<String> lines = Files.readAllLines(path); // 读取内容
74. Java NIO的Files类有哪些常用方法?
Files
类的常用方法包括:
createFile(Path)
:创建文件。write(Path, byte[])
:写入字节到文件。readAllBytes(Path)
:读取文件所有字节。copy(Path, Path)
:复制文件。delete(Path)
:删除文件。exists(Path)
:检查文件是否存在。
75. 什么是Java NIO的WatchService?
WatchService
是Java NIO提供的一个用于监控文件系统变化的机制,可以监听目录中的文件创建、修改、删除等事件。
76. WatchService的作用是什么?
WatchService
的作用是实时监控文件系统的变化,当指定目录中的文件发生修改时,能够及时通知应用程序,适用于需要响应文件变化的场景。
77. 如何使用WatchService监控文件变化?
使用WatchService
的步骤如下:
- 获取
WatchService
实例。 - 注册要监控的目录和事件类型。
- 循环等待并处理事件。
示例代码:
WatchService watchService = FileSystems.getDefault().newWatchService();
Path dir = Paths.get("path/to/dir");
dir.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
// 处理事件
}
key.reset();
}
78. Java NIO的AsynchronousChannel是什么?
AsynchronousChannel
是Java NIO中支持异步I/O操作的通道接口,允许应用程序在I/O操作完成时得到通知,而无需阻塞等待。
79. AsynchronousChannel的作用是什么?
AsynchronousChannel
的作用是提供非阻塞的I/O操作,提高应用程序的并发性能和响应速度,特别适用于高并发的网络通信和文件操作。
80. 如何使用AsynchronousChannel进行异步IO操作?
通过AsynchronousFileChannel
、AsynchronousSocketChannel
等实现类进行异步I/O操作,例如:
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("file.txt"));
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
// 读取完成后的处理
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
// 读取失败的处理
}
});
81. 什么是AsynchronousFileChannel?
AsynchronousFileChannel
是Java NIO中用于异步文件I/O操作的通道类,支持在后台线程中执行文件读写操作,并通过回调机制通知操作结果。
82. 如何使用AsynchronousFileChannel进行异步文件IO?
使用AsynchronousFileChannel
的read()
和write()
方法,并传入CompletionHandler
来处理异步操作的结果,例如:
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("file.txt"));
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
// 处理读取的数据
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
// 处理错误
}
});
83. 什么是AsynchronousSocketChannel?
AsynchronousSocketChannel
是Java NIO中用于异步网络通信的通道类,支持非阻塞的TCP连接和数据传输。
84. 如何使用AsynchronousSocketChannel进行异步网络通信?
通过AsynchronousSocketChannel
的connect()
、read()
和write()
方法进行异步网络通信,例如:
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
channel.connect(new InetSocketAddress("localhost", 8080), null, new CompletionHandler<Void, Void>() {
@Override
public void completed(Void result, Void attachment) {
// 连接成功后的操作
}
@Override
public void failed(Throwable exc, Void attachment) {
// 连接失败的处理
}
});
85. 什么是AsynchronousServerSocketChannel?
AsynchronousServerSocketChannel
是Java NIO中用于异步监听和接受TCP连接的通道类,支持高并发的网络服务器实现。
86. 如何使用AsynchronousServerSocketChannel进行异步服务器通信?
通过AsynchronousServerSocketChannel
的bind()
和accept()
方法实现异步服务器,例如:
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();
server.bind(new InetSocketAddress(8080));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
@Override
public void completed(AsynchronousSocketChannel client, Void attachment) {
// 处理客户端连接
server.accept(null, this); // 继续接受新连接
}
@Override
public void failed(Throwable exc, Void attachment) {
// 处理错误
}
});
87. Java NIO与传统IO在API设计上的区别是什么?
Java NIO的API设计更加面向对象和灵活,使用通道(Channel)和缓冲区(Buffer)进行数据传输,支持非阻塞I/O和选择器(Selector)实现多路复用。而传统IO的API设计较为简单,基于流(Stream)模型,仅支持阻塞I/O。
88. Java NIO的线程模型是什么?
Java NIO的线程模型支持单线程管理多个通道(通过Selector),适用于高并发场景。通过事件驱动的方式,一个线程可以处理多个I/O操作,减少了线程切换的开销。
89. Java NIO的多线程编程需要注意什么?
在使用Java NIO进行多线程编程时,需要注意:
- 共享资源(如Selector)的线程安全性。
- 避免在I/O回调中执行耗时操作,防止阻塞事件循环。
- 合理分配线程资源,避免过度竞争。
90. 如何在Java NIO中处理异常?
在Java NIO中,异常处理通常通过try-catch
块捕获I/O操作抛出的异常(如IOException
),并在回调方法(如CompletionHandler
的failed()
方法)中处理异步操作的错误。例如:
try {
FileChannel channel = FileChannel.open(path, StandardOpenOption.READ);
// 操作channel
} catch (IOException e) {
// 处理异常
}