Java NIO完整教程:通道、缓冲区和选择器实战详解
Java NIO是Java 1.4引入的高性能I/O API,相比传统I/O具有非阻塞和异步操作优势。本文系统讲解NIO三大核心组件的工作原理,通过文件操作、网络服务器与客户端通信、缓冲区管理等实际代码示例,详细演示了NIO在高并发场景下的应用。内容涵盖从基础概念到实战应用的全流程,帮助开发者快速掌握NIO编程技巧,提升I/O处理效率。
Java NIO 是 Java 1.4 引入的新I/O API,提供了非阻塞、异步的I/O操作能力,相比传统的Java I/O API更高效。
核心组件
1、通道 (Channel) - 数据的传输通道
2、缓冲区 (Buffer) - 数据容器
3、选择器 (Selector) - 多路复用器,用于管理多个通道
示例代码
1. 文件读写示例
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class NIOFileExample {
public static void main(String[] args) {
// 写入文件
writeToFile("example.txt", "Hello, Java NIO!");
// 读取文件
readFromFile("example.txt");
}
// 写入文件
public static void writeToFile(String filename, String content) {
try (RandomAccessFile file = new RandomAccessFile(filename, "rw");
FileChannel channel = file.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(content.getBytes());
buffer.flip(); // 切换为读模式
while (buffer.hasRemaining()) {
channel.write(buffer);
}
System.out.println("文件写入完成");
} catch (IOException e) {
e.printStackTrace();
}
}
// 读取文件
public static void readFromFile(String filename) {
try (RandomAccessFile file = new RandomAccessFile(filename, "r");
FileChannel channel = file.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = channel.read(buffer);
buffer.flip(); // 切换为读模式
byte[] data = new byte[bytesRead];
buffer.get(data);
System.out.println("读取内容: " + new String(data));
} catch (IOException e) {
e.printStackTrace();
}
}
}2. 网络服务器示例
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class NIOServer {
private static final int PORT = 8080;
public static void main(String[] args) throws IOException {
// 创建选择器
Selector selector = Selector.open();
// 创建服务器通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(PORT));
// 注册到选择器,监听接受连接事件
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务器启动,监听端口: " + PORT);
while (true) {
// 阻塞直到有事件发生
selector.select();
// 获取就绪的事件
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
if (key.isAcceptable()) {
handleAccept(serverChannel, selector);
}
if (key.isReadable()) {
handleRead(key);
}
iter.remove();
}
}
}
private static void handleAccept(ServerSocketChannel serverChannel, Selector selector)
throws IOException {
SocketChannel client = serverChannel.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
System.out.println("客户端连接: " + client.getRemoteAddress());
}
private static void handleRead(SelectionKey key) throws IOException {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = client.read(buffer);
if (bytesRead == -1) {
client.close();
System.out.println("客户端断开连接");
return;
}
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String message = new String(data);
System.out.println("收到消息: " + message);
// 回显消息
ByteBuffer response = ByteBuffer.wrap(("服务器回复: " + message).getBytes());
client.write(response);
}
}3. 网络客户端示例
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class NIOClient {
public static void main(String[] args) throws IOException {
SocketChannel client = SocketChannel.open();
client.configureBlocking(false);
client.connect(new InetSocketAddress("localhost", 8080));
// 等待连接完成
while (!client.finishConnect()) {
System.out.println("正在连接服务器...");
}
System.out.println("连接服务器成功!");
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入消息 (输入exit退出): ");
String message = scanner.nextLine();
if ("exit".equalsIgnoreCase(message)) {
break;
}
// 发送消息
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
client.write(buffer);
// 接收响应
ByteBuffer response = ByteBuffer.allocate(1024);
int bytesRead = client.read(response);
if (bytesRead > 0) {
response.flip();
byte[] data = new byte[response.remaining()];
response.get(data);
System.out.println("服务器响应: " + new String(data));
}
}
client.close();
scanner.close();
}
}4. Buffer 操作示例
import java.nio.ByteBuffer;
public class BufferExample {
public static void main(String[] args) {
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(10);
System.out.println("初始状态:");
printBufferInfo(buffer);
// 写入数据
byte[] data = "Hello".getBytes();
buffer.put(data);
System.out.println("\n写入数据后:");
printBufferInfo(buffer);
// 切换为读模式
buffer.flip();
System.out.println("\nflip()后:");
printBufferInfo(buffer);
// 读取数据
System.out.println("\n读取数据:");
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println();
System.out.println("\n读取完成后:");
printBufferInfo(buffer);
// 清空缓冲区
buffer.clear();
System.out.println("\nclear()后:");
printBufferInfo(buffer);
}
private static void printBufferInfo(ByteBuffer buffer) {
System.out.println("Position: " + buffer.position());
System.out.println("Limit: " + buffer.limit());
System.out.println("Capacity: " + buffer.capacity());
System.out.println("Remaining: " + buffer.remaining());
}
}NIO 的优势
1、非阻塞 I/O - 线程不需要等待I/O操作完成
2、选择器机制 - 单个线程可以管理多个通道
3、内存映射文件 - 可以直接操作文件内存
4、更高效的缓冲区操作
使用场景
1、高并发网络服务器
2、大文件处理
3、需要高性能I/O的应用
4、实时数据处理系统
这些示例展示了Java NIO的基本用法,包括文件操作、网络通信和缓冲区管理。NIO在处理高并发I/O时比传统I/O更高效,但代码相对复杂一些。
最后更新于3月前
本文由人工编写,AI优化,转载请注明原文地址: Java NIO使用指南:核心组件详解与实战代码示例
推荐阅读
评论 (1)
发表评论
昵称:加载中...
小草莓🍓2025-11-08 19:00:20
最近正好在优化项目的文件处理模块,用NIO改造后性能提升很明显。示例代码很实用,特别是Buffer的flip操作,之前在这里踩过坑。