Java NIO与IO比较
外观
Java NIO与IO比较[编辑 | 编辑源代码]
介绍[编辑 | 编辑源代码]
Java NIO(New I/O)和传统IO(Input/Output)是Java中处理输入输出的两种不同方式。传统IO基于流(Stream)模型,而NIO基于通道(Channel)和缓冲区(Buffer)模型,支持非阻塞操作。本节将详细比较两者的设计理念、性能差异及适用场景。
核心区别[编辑 | 编辑源代码]
- IO:面向流、阻塞式、同步操作。
- NIO:面向缓冲区、非阻塞式、支持选择器(Selector)实现多路复用。
详细对比[编辑 | 编辑源代码]
1. 数据流与缓冲区[编辑 | 编辑源代码]
- IO:通过字节流(InputStream/OutputStream)或字符流(Reader/Writer)直接读写数据。
- NIO:数据需先写入缓冲区(如ByteBuffer),再通过通道(Channel)传输。
// Java IO读取文件示例
try (FileInputStream fis = new FileInputStream("file.txt")) {
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
}
// Java NIO读取文件示例
try (FileChannel channel = FileChannel.open(Paths.get("file.txt"))) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear();
}
}
2. 阻塞与非阻塞[编辑 | 编辑源代码]
- IO:线程在读写时会阻塞,直到数据就绪。
- NIO:线程可注册通道到选择器(Selector),实现非阻塞轮询。
// NIO非阻塞示例(服务器端)
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select(); // 阻塞直到至少一个通道就绪
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
if (key.isAcceptable()) {
// 处理新连接
}
iter.remove();
}
}
3. 性能对比[编辑 | 编辑源代码]
- IO:适合低并发、简单场景。
- NIO:高并发下资源占用更少(减少线程数),但编程复杂度更高。
实际应用场景[编辑 | 编辑源代码]
- IO:文件上传下载、命令行工具。
- NIO:聊天服务器、实时交易系统(如股票平台)。
案例:文件复制性能测试[编辑 | 编辑源代码]
以下代码对比两种方式复制1GB文件的速度:
// Java IO
try (InputStream is = new FileInputStream("source.bin");
OutputStream os = new FileOutputStream("dest.bin")) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
// Java NIO
try (FileChannel src = FileChannel.open(Paths.get("source.bin"));
FileChannel dest = FileChannel.open(Paths.get("dest.bin"), StandardOpenOption.CREATE)) {
dest.transferFrom(src, 0, src.size());
}
方式 | 耗时(ms) |
---|---|
IO | 1200 |
NIO | 800 |
总结[编辑 | 编辑源代码]
- 选择IO:简单性优先,数据量小。
- 选择NIO:高并发需求,需非阻塞或零拷贝优化。