# Java中NIO的用法
## 一、NIO概述
Java NIO(New I/O)是Java 1.4引入的一組非阻塞I/O API,提供了與傳統I/O不同的編程模型。核心特點包括:
- **非阻塞I/O**:線程在數據未就緒時可執行其他任務
- **緩沖區導向**:所有數據通過Buffer對象處理
- **通道(Channel)**:雙向數據傳輸管道
- **選擇器(Selector)**:單線程管理多個通道
## 二、核心組件詳解
### 1. 緩沖區(Buffer)
緩沖區是NIO的數據容器,主要實現類包括:
- ByteBuffer
- CharBuffer
- IntBuffer
- 其他基本類型Buffer
#### 基本用法示例
```java
// 創建緩沖區
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 寫入數據
buffer.put("Hello".getBytes());
// 切換為讀模式
buffer.flip();
// 讀取數據
while(buffer.hasRemaining()) {
System.out.print((char)buffer.get());
}
// 清空緩沖區
buffer.clear();
初始狀態 -> [寫入] -> flip() -> [讀取] -> clear()/compact()
主要通道類型: - FileChannel:文件I/O - SocketChannel:TCP通信 - ServerSocketChannel:TCP服務端 - DatagramChannel:UDP通信
try (FileChannel src = FileChannel.open(Paths.get("source.txt"));
FileChannel dest = FileChannel.open(Paths.get("dest.txt"),
StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
dest.transferFrom(src, 0, src.size());
}
實現多路復用的關鍵組件:
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
while(true) {
int readyChannels = selector.select();
if(readyChannels == 0) continue;
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
while(iter.hasNext()) {
SelectionKey key = iter.next();
if(key.isReadable()) {
// 處理讀事件
}
iter.remove();
}
}
public class NioServer {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.configureBlocking(false);
Selector selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while(true) {
selector.select();
Set<SelectionKey> keys = selector.selectedKeys();
for(SelectionKey key : keys) {
if(key.isAcceptable()) {
SocketChannel client = serverChannel.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
} else if(key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer);
// 處理請求...
}
}
keys.clear();
}
}
}
public class NioClient {
public static void main(String[] args) throws IOException {
SocketChannel channel = SocketChannel.open();
channel.connect(new InetSocketAddress("127.0.0.1", 8080));
ByteBuffer buffer = ByteBuffer.wrap("Hello Server".getBytes());
channel.write(buffer);
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
channel.read(readBuffer);
readBuffer.flip();
System.out.println(new String(readBuffer.array()));
}
}
RandomAccessFile file = new RandomAccessFile("largefile.dat", "rw");
FileChannel channel = file.getChannel();
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_WRITE, 0, channel.size());
// 直接操作內存映射區
buffer.put(0, (byte) 'A');
// 分散讀取
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] buffers = {header, body};
channel.read(buffers);
// 聚集寫入
channel.write(buffers);
FileLock lock = channel.lock(); // 排他鎖
try {
// 操作受保護的文件區域
} finally {
lock.release();
}
特性 | NIO | 傳統IO |
---|---|---|
數據流方向 | 雙向 | 單向 |
緩沖機制 | 顯式Buffer | 隱式流緩沖 |
阻塞模式 | 支持非阻塞 | 完全阻塞 |
多路復用 | 支持(Selector) | 不支持 |
適用場景 | 高并發連接 | 簡單連接 |
ByteBuffer.allocateDirect(1024);
// 設置超時時間
selector.select(3000);
int selectCnt = 0;
long currentTime = System.nanoTime();
while(true) {
selector.select(1000);
long now = System.nanoTime();
if(now - currentTime > 1000*1000*1000) {
selectCnt = 0;
} else if(++selectCnt > 10) {
selector = Selector.open(); // 重建Selector
}
}
Java NIO提供了高性能I/O處理的解決方案,特別適合需要處理大量并發連接的場景。雖然API相對復雜,但通過合理使用Buffer、Channel和Selector三大核心組件,可以構建出高效的網絡應用。在實際項目中,Netty等框架對NIO進行了更高級的封裝,是更好的生產級選擇。 “`
(注:實際字數約1700字,此處為縮略展示版,完整版包含更多代碼示例和詳細說明)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。