NIO
NIO(Non-blocking IO)是Java 1.4引入的新IO API,支持面向缓冲区、基于通道的IO操作。
NIO概述
NIO含义
- Non-blocking IO(非阻塞IO)
- 也称为New IO
NIO与传统IO的区别
| 对比项 | 传统IO | NIO |
|---|---|---|
| 面向对象 | 流(Stream) | 缓冲区(Buffer)+通道(Channel) |
| 数据流向 | 单向 | 双向(可读可写) |
| 阻塞模式 | 阻塞 | 支持非阻塞 |
| 效率 | 一般 | 更高(利用系统原生IO) |
| 适用场景 | 简单文件读写 | 高并发网络IO、大文件 |
NIO核心组件
三大核心
- Buffer:缓冲区,存储数据
- Channel:通道,传输数据
- Selector:选择器,多路复用(网络IO)
工作模式
Java
数据源 ←────── Channel ←────── Buffer ←────── 程序
(文件) (缓冲区)
Buffer缓冲区
Buffer的作用
在内存中存储数据,程序读写Buffer,Buffer与Channel交互。
常用Buffer类型
| Buffer类型 | 说明 |
|---|---|
| ByteBuffer | 字节缓冲区(最常用) |
| CharBuffer | 字符缓冲区 |
| IntBuffer | 整数缓冲区 |
| LongBuffer | 长整数缓冲区 |
Buffer核心属性
| 属性 | 说明 |
|---|---|
| capacity | 容量,Buffer最大数据量 |
| position | 当前读写位置 |
| limit | 限制,可用数据的边界 |
Buffer使用流程
Java
// 1. 创建Buffer
ByteBuffer buffer = ByteBuffer.allocate(1024); // 分配1024字节
// 2. 写入数据
buffer.put("Hello".getBytes());
// 3. 切换为读模式
buffer.flip(); // position置0,limit置已写数据量
// 4. 读取数据
byte[] data = new byte[buffer.limit()];
buffer.get(data);
// 5. 清空,准备再次写入
buffer.clear(); // position置0,limit置capacity
关键:写后必须flip()切换为读模式,读后clear()清空准备下次写入。
Channel通道
Channel的作用
连接数据源,负责数据传输,可双向读写。
常用Channel类型
| Channel类型 | 说明 |
|---|---|
| FileChannel | 文件通道 |
| SocketChannel | TCP网络通道 |
| DatagramChannel | UDP网络通道 |
FileChannel使用
从文件读取
Java
// 创建FileChannel
FileChannel channel = new FileInputStream("test.txt").getChannel();
// 创建Buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 从Channel读取到Buffer
int bytesRead = channel.read(buffer);
while (bytesRead != -1) {
buffer.flip(); // 切换为读模式
// 处理buffer数据
buffer.clear(); // 清空准备下次读取
bytesRead = channel.read(buffer);
}
channel.close();
写入文件
Java
FileChannel channel = new FileOutputStream("test.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Hello World".getBytes());
buffer.flip(); // 切换为读模式
channel.write(buffer); // 从Buffer写到Channel
channel.close();
文件复制(高效)
Java
FileChannel src = new FileInputStream("source.jpg").getChannel();
FileChannel dest = new FileOutputStream("target.jpg").getChannel();
// transferTo高效复制(底层优化)
src.transferTo(0, src.size(), dest);
src.close();
dest.close();
Selector选择器
Selector的作用
多路复用,一个线程管理多个Channel,适合高并发网络应用。
使用场景
- 服务器需要同时处理多个客户端连接
- 避免为每个连接创建线程
- 非阻塞模式提高并发能力
基本流程(网络IO)
text
// 1. 创建Selector
Selector selector = Selector.open();
// 2. 注册Channel到Selector
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false); // 设置非阻塞
channel.register(selector, SelectionKey.OP_READ); // 注册读事件
// 3. 选择就绪的Channel
while (true) {
int readyCount = selector.select(); // 等待事件
if (readyCount == 0) continue;
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if (key.isReadable()) {
// 处理读取
}
}
keys.clear();
}
Selector用于网络IO,文件IO通常不需要Selector。
NIO适用场景
| 场景 | 推荐 |
|---|---|
| 简单文件读写 | 传统IO + 缓冲流 |
| 大文件复制 | NIO FileChannel.transferTo |
| 高并发网络服务器 | NIO + Selector |
| 少量连接客户端 | 传统IO即可 |
建议:简单场景用传统IO,高并发/大文件用NIO。
要点总结
- NIO面向缓冲区,传统IO面向流
- NIO核心:Buffer、Channel、Selector
- Buffer存储数据,flip/clear切换读写模式
- Channel双向传输,FileChannel处理文件
- Selector多路复用,适合高并发网络
- 简单场景传统IO,高并发/大文件用NIO
- transferTo高效复制大文件
📝 发现内容有误?点击此处直接编辑