Java的NIO(New Input/Output)是从Java 1.4版本开始引入的一套新的IO API,用来替代标准Java IO API。NIO支持面向缓冲区的(Buffer-oriented)、基于通道的(Channel-based)IO操作。NIO旨在提高IO操作的速度,并提供更加强大的IO功能,比如非阻塞式的IO。
NIO与传统IO的主要区别
1. 面向流 vs 面向缓冲区
- 传统IO是面向流的,它是直接对数据流进行操作。
- NIO是面向缓冲区的,数据首先读入到缓冲区,然后操作缓冲区中的数据。
2. 阻塞式 vs 非阻塞式
- 传统IO的各种操作是阻塞式的。例如,当一个线程调用
read()
或write()
时,它会一直阻塞在那里,直到有一些数据被完全读取或写入。 - NIO可以设置为非阻塞模式。在非阻塞模式下,一个线程可以请求读写操作,即使没有数据可用,也不会阻塞。这使得一个线程可以管理多个输入和输出通道(channel)。
3. 选择器(Selectors)
- NIO引入了选择器(Selectors)的概念,这是一种能够监控多个通道(Channels)上IO事件(比如读、写)的对象。这意味着一个单独的线程可以管理多个通道内的数据,这使得NIO可以提供更高的性能,尤其是在需要管理成百上千个通道的时候。
代码举例
传统IO示例(读取文件)
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;public class ClassicIOExample {public static void main(String[] args) {BufferedReader reader = null;try {reader = new BufferedReader(new FileReader("example.txt"));String line = null;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}
}
NIO示例(读取文件)
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class NIOExample {public static void main(String[] args) {FileInputStream fis = null;try {fis = new FileInputStream("example.txt");FileChannel channel = fis.getChannel();ByteBuffer buffer = ByteBuffer.allocate(1024);while (channel.read(buffer) != -1) {buffer.flip(); // 切换模式,写->读while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}buffer.clear(); // 清空缓冲区,等待下次读取}} catch (IOException e) {e.printStackTrace();} finally {if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}}
}
在这个NIO的例子中,通过FileChannel
(通道)和ByteBuffer
(缓冲区)来读取文件内容,体现了NIO面向缓冲区、基于通道的设计思想,同时也展示了NIO与传统IO操作的根本差异。