ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【NIO】3.2 ByteBuffer的原理-AI参考

【NIO】3.2 ByteBuffer的原理-AI参考 NIO 中的Buffer缓冲区是 Java NIO 的核心组件之一它是一个用于存储特定基本类型数据的容器。所有 NIO 的 I/O 操作都是通过 Buffer 来进行的——数据总是从 Channel 读入 Buffer或从 Buffer 写入 Channel。一、Buffer 的基本类型Java NIO 提供了 7 种主要的 Buffer 实现对应 7 种基本数据类型除了 boolean类型说明ByteBuffer最常用其他类型可通过它转换CharBuffer字符缓冲区ShortBuffer短整型缓冲区IntBuffer整型缓冲区LongBuffer长整型缓冲区FloatBuffer浮点缓冲区DoubleBuffer双精度缓冲区其中ByteBuffer是最核心的因为网络和文件 I/O 的底层都是字节流。二、Buffer 的四个核心属性理解 Buffer 的关键在于掌握它的四个属性publicabstractclassBuffer{privateintmark-1;// 标记位置privateintposition0;// 当前位置privateintlimit;// 限制位置privateintcapacity;// 容量}1. capacity容量Buffer 能容纳的最大数据量创建后不可改变。2. position位置下一个要被读或写的元素的索引。写模式下写入数据的位置。读模式下读取数据的位置。3. limit限制缓冲区中可读/可写的边界不能超过 limit。写模式limit capacity。读模式limit 之前写入的数据量。4. mark标记一个临时记录的位置通过mark()设置reset()恢复到该位置。关系恒成立0 mark position limit capacity三、核心方法1. 读写操作// 写数据position 递增buffer.put((byte)1);// 读数据position 递增bytebbuffer.get();2. flip() —— 写模式切换为读模式publicfinalBufferflip(){limitposition;// limit 设为已写入的数据量position0;// position 归零mark-1;returnthis;}这是最容易出错的地方写完数据要读之前必须调用flip()。3. clear() —— 清空缓冲区publicfinalBufferclear(){position0;limitcapacity;mark-1;returnthis;}注意clear()并不真正清除数据只是重置指针数据会被后续写入覆盖。4. compact() —— 保留未读数据publicabstractByteBuffercompact();将未读的数据复制到缓冲区起始处然后切换到写模式。用于读取部分数据后继续写入的场景。5. rewind() —— 重读publicfinalBufferrewind(){position0;mark-1;returnthis;}将 position 归零可以重新读取已读过的数据limit 不变。6. mark() 和 reset()buffer.mark();// 记录当前 positionbuffer.reset();// 恢复到 mark 的位置四、状态转换示意图初始状态刚创建: 0 capacity | | position0, limitcapacity 写入 3 个字节后: 0 1 2 3 capacity | | | position3, limitcapacity 调用 flip() 后切换到读模式: 0 1 2 3 | | position0, limit3 读取 2 个字节后: 0 1 2 3 | | position2, limit3 调用 clear() 后回到写模式: 0 1 2 3 capacity | | position0, limitcapacity五、使用示例publicclassBufferDemo{publicstaticvoidmain(String[]args){// 创建容量为 10 的 ByteBufferByteBufferbufferByteBuffer.allocate(10);// 写模式buffer.put((byte)H);buffer.put((byte)e);buffer.put((byte)l);buffer.put((byte)l);buffer.put((byte)o);// 切换到读模式buffer.flip();// 读取数据while(buffer.hasRemaining()){System.out.print((char)buffer.get());}// 输出: Hello// 清空准备下次写入buffer.clear();}}六、allocate vs allocateDirect// 1. 堆内存缓冲区JVM 堆中ByteBufferheapBufferByteBuffer.allocate(1024);// 2. 直接内存缓冲区操作系统内存零拷贝ByteBufferdirectBufferByteBuffer.allocateDirect(1024);对比项allocate堆allocateDirect直接内存位置JVM 堆堆外OS 内存分配/回收速度快慢I/O 性能较低需复制高零拷贝适用场景普通场景高频 I/O、大文件七、其他常用方法buffer.remaining();// limit - position剩余可读/可写数量buffer.hasRemaining();// 是否还有剩余buffer.rewind();// 重置 position 为 0可重读buffer.slice();// 创建一个共享数据的子缓冲区buffer.duplicate();// 复制一个缓冲区共享数据独立属性buffer.asReadOnlyBuffer();// 创建只读缓冲区八、常见误区忘记 flip()写完直接读会读到 position 之后的位置导致读不到数据。混淆 clear() 和真正清空clear()只重置指针不擦除内容。读完后直接 clear() 导致未读数据丢失应使用compact()保留未读数据。多次 flip()flip 只能调一次第二次调用会把 limit 设为 0。九、总结Buffer 是 NIO 数据读写的桥梁核心在于四个属性的流转写数据→ position 增加flip()→ 切换到读模式读数据→ position 增加clear()/compact()→ 切换回写模式掌握 position、limit、capacity 三者的变化就掌握了 Buffer 的本质。
返回列表