Java NIO之Buffer

与 NIO Channel 进行交互时, 需要使用 NIO Buffer, 将数据从 Buffer读取到 Channel 或者从 Channel 中写入Buffer 中.

Buffer 类型有: ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、 IntBuffer、LongBuffer、

ShortBuffer。

Buffer类中有 limit,position,mark,capacity几个属性

capacity :容量,表示Buffer空间大小,最多写入的单位数据。

position :读写操作的位置指针

写模式时,表示写入的当前位置,初始值为0,从position位置开始写入,写入一个单位数据时,该值加1,最大值为capacity-1.

调用flip方法将模式转换为读模式时,position会置为0,当读取一个单位数据时,position加1

limit :当前buffer可操作的数据量,通常小于等于容量

写模式时,表示可对buffer最多写入的数据量,写模式时,limit=capacity

读模式时,表示buffer中还有多少单位的数据可以读取

mark :标记,是一个临时位置的引用。使用mark()方法来标记当前位置,之后用reset()可以将位置重置到标记位置

NIO Buffer 的基本方法

allocate (n): 分配Buffer内存空间,实际分配的内存空间与buffer类型有关( n*siezeof(type))

put ():向buffer中写入数据

写数据到buff中有两种方式:

1):int bytesRead = inChannel.read(buf); //从Channel写到Buffer.

2):buf.put(...);

flip():Buffer 切换为读模式.

java 复制代码
// flip 方法源码  
public final Buffer flip() {
      limit = position;
      position = 0;
      mark = -1;
      return this;
 }

get ():读取一个单位的数据

clear(): 清空buffer。读完所有数据后,如需要再次写入,则需clear()来清空buffer,但其中数据并未被真实清除,而只是告诉我们从哪里开始往buffer中写入数据

java 复制代码
// clear方法源码:
public final Buffer clear() {       
    position = 0;    
    limit = capacity;        
    mark = -1;
    return this;
}

compact (): 如还有未读数据,使用该方法可将剩余数据移到Buffer的开始位置,然后将position设置为最后一个未读元素之后的位置,调用该方法后可直接向buff而写入数据,就不会覆盖未读数据。

rewind():倒带,将posiiton置位0,可以重读buffer中的所有数据

java 复制代码
//rewind 方法源码
public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
}

mark (): 标记buffer中某特定position,之后可以通过reset方法,将position恢复到该标志位

reset ():回滚

将数据写入到 Buffer 中时, Buffer 会记录写了多少的数据, 当从 Buffer 中读数据时, 必须调用 Buffer.flip()将 Buffer 切换为读模式.

读取了所有的 Buffer 数据后, 必清理 Buffer, 让其重新可写, 清理 Buffer 可以调用 clear() 或 compact()方法, 将 Buffer 转换为写模式.

关于 Direct Buffer 和 Non-Direct Buffer

Direct Buffer (直接缓冲器): 不在 JVM 堆上分配的内存, 不受 GC 的管理.

使用了堆外内存,不需要JVM 拷贝 buffer 中的数据到中间临时缓冲区中,减少了数据的复制次数,从而提高了性能。在处理大量数据时,使用直接Buffer可以避免额外的数据复制操作,进一步优化了性能

申请和释放 Direct Buffer 的开销比较大. 因此正确的使用 Direct Buffer 的方式是在初始化时申请一个 Buffer, 然后不断复用此 buffer, 在程序结束后才释放此 buffer.

要分配直接缓冲区,需要调用allocateDirect()方法,而不是allocate()方法,使用方式与普通缓冲区一致。

Non-Direct Buffer : 直接在 JVM 堆上分配的内存, 本质上是 byte[] 数组的封装.

因为 Non-Direct Buffer 在 JVM 堆中, 当进行操作系统底层 IO 操作中时, 需要将数据从Java堆复制到堆外内存,会导致额外的性能开销. 因此 Non-Direct Buffer 的效率较低.

相关推荐
草莓熊Lotso几秒前
【C语言编译与链接】--翻译环境和运行环境,预处理,编译,汇编,链接
c语言·开发语言·汇编·经验分享·笔记·其他
byte轻骑兵8 分钟前
【C++高级主题】命令空间(三):未命名的命名空间
开发语言·c++
季鸢31 分钟前
Java设计模式之中介者模式详解
java·设计模式·中介者模式
小马爱打代码32 分钟前
设计模式:观察者模式 - 实战
java·观察者模式·设计模式
txz203537 分钟前
1,QT的编译教程
开发语言·数据库·qt
yy_xzz44 分钟前
Qt 窗口标志(Window Flags)详解:控制窗口样式与行为
开发语言·qt
失败尽是常态Z1 小时前
基于JWT+Redis的登录流程实现
java·数据库·redis·状态模式·jwt·用户登录
快乐肚皮1 小时前
Redisson学习专栏(二):核心功能深入学习(分布式锁,分布式集合,原子操作与计数器,事件与监听)
java·分布式·分布式锁·redisson·事件·分布式集合·原子
即安莉1 小时前
ESP8266远程控制:实现网络通信与设备控制
开发语言·stm32·单片机·嵌入式硬件·php
Mr YiRan1 小时前
Kotlin委托机制使用方式和原理
android·开发语言·kotlin