Java NIO 核心组件概述

Java NIO(New I/O)通过非阻塞I/O模型提高高并发场景下的性能,核心组件包括:

  • 缓冲区(Buffer):临时存储数据的容器,支持读写操作。
  • 通道(Channel):连接数据源与缓冲区的双向数据传输管道。
  • 选择器(Selector):监控多个通道的事件(如连接、读写),实现单线程多路复用。

缓冲区的使用

缓冲区通过ByteBufferCharBuffer等类实现,操作流程如下:

  1. 分配空间
    ByteBuffer buffer = ByteBuffer.allocate(1024); // 分配堆内存
    ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024); // 直接内存(减少拷贝)  
    

  2. 写入数据
    buffer.put("Hello".getBytes());  
    buffer.flip(); // 切换为读模式(limit=position, position=0)  
    

  3. 读取数据
    while (buffer.hasRemaining()) {  
        System.out.print((char) buffer.get());  
    }  
    buffer.clear(); // 清空缓冲区(position=0, limit=capacity)  
    

关键属性

  • position:当前读写位置。
  • limit:可操作数据边界。
  • capacity:缓冲区容量。

通道的操作

通道通过FileChannelSocketChannel等类实现数据传输。

文件通道示例

try (FileChannel inChannel = FileChannel.open(Paths.get("input.txt"));  
     FileChannel outChannel = FileChannel.open(Paths.get("output.txt"),  
         StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {  
    inChannel.transferTo(0, inChannel.size(), outChannel); // 零拷贝文件传输  
}  

网络通道示例

SocketChannel socketChannel = SocketChannel.open();  
socketChannel.configureBlocking(false); // 非阻塞模式  
socketChannel.connect(new InetSocketAddress("example.com", 80));  


选择器的多路复用

选择器通过监听通道事件实现高并发处理。

注册与监听流程

  1. 创建选择器
    Selector selector = Selector.open();  
    

  2. 注册通道事件
    socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_CONNECT);  
    

  3. 事件循环处理
    while (true) {  
        int readyChannels = selector.select(); // 阻塞直到事件就绪  
        Set<SelectionKey> keys = selector.selectedKeys();  
        for (SelectionKey key : keys) {  
            if (key.isReadable()) {  
                // 处理读事件  
            }  
            keys.remove(key);  
        }  
    }  
    

事件类型

  • OP_READ:数据可读。
  • OP_WRITE:数据可写。
  • OP_CONNECT:连接就绪。
  • OP_ACCEPT:服务端接受连接。

实际应用场景

  1. 高性能文件传输:结合FileChannel.transferTo()实现零拷贝。
  2. 非阻塞网络通信:通过Selector管理多个SocketChannel,减少线程开销。
  3. 自定义协议解析:使用ByteBuffer灵活处理二进制数据。

注意事项

  • 直接内存缓冲区(allocateDirect)适合高频I/O操作,但分配成本较高。
  • 非阻塞模式下需处理未完成连接(finishConnect())。
  • 选择器的selectedKeys集合需手动移除已处理键。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐