# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。