我报名参加金石方案1期挑战——分割10万奖池,这是我的第4篇文章,点击查看活动详情
在Java网络开发的过程中触摸NIO是必不可少的,在NIO中有一个重要的组件那就是 ByteBuffer
,下面就来通过图文的方式来讲解ByteBuffer的运用以及一些操作的原理。
1. ByteBuffer完成原理
对于ByteBuffer来说首要有五个重要属性如下:
- mark(int类型): 记载当前索引的方位
- position(int类型): 读形式:表明接下来能够读取的数据方位, 写形式:表明能够写入数据的方位
- limit(int类型): 读形式:表明能够写入数据巨细,写形式:表明能够写入数据巨细。 默许是ByteBuffer的capacity
- capacity(int类型): ByteBuffer的容量
- hb(byte array): 实际数据存储byte数组
Tips: 几个数据之间的巨细联系mark <= position <= limit <= capacity
示意图如下:
2. 读写形式
ByteBuffer首要有读写形式,Java原生的和Netty的ByteBuf有不同的。ByteBuffer的读写形式需要自己进行切换。
2.1 写形式
写形式示意图如下:
从上图能够看出来初始化后capacity是固定了。limit的值能够进行设置。当有新的数据写入position指针会进行移动。能写入的数据由limit确认。
2.2 读形式
读形式示意图如下:
如何把写入的数据读取出来,首先要将写形式转化成成读的形式。否则会读形式会在在写的指针往后进行读取。随着数据读取position指针也会进行移动,limit会约束指针移动的方位。
Tips: flip 方法用于读写形式切换
对于ByteBuffer首要是弄清楚四个变量 position、limit、mark、capacity
四者之间的联系转化以及读写的联系转化。
3. 运用示例
下面会结合例子以及示图来说明ByteBuffer的一些基本运用和一些常见API的操作。如下是一个简略的运用示例:
public class ByteBufferExample {
public static void main(String[] args) {
ByteBuffer allocate = ByteBuffer.allocate(20); //分配一个巨细为20bytes的ByteBuffer
System.out.println(allocate.capacity()); //20
System.out.println(allocate.limit()); // 20
System.out.println(allocate.position()); //0
System.out.println("--------------------");
allocate.putLong(10L);
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//20
System.out.println(allocate.position());//8
System.out.println("--------------------");
System.out.println(allocate.getLong());
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//20
System.out.println(allocate.position());//16
}
}
不同的变量变化的示意图如下:
上面代码中没有进行读写形式转化的。position指针不论读仍是写会一直往capacity方位接近。
3.1 flip-API
运用示例代码如下:
public static void main(String[] args) throws Exception{
ByteBuffer allocate = ByteBuffer.allocate(20); //分配一个巨细为20bytes的ByteBuffer
allocate.putLong(10L);
System.out.println(allocate.capacity()); //20
System.out.println(allocate.limit()); // 20
System.out.println(allocate.position()); //8
System.out.println("--------------------");
allocate.flip();
System.out.println(allocate.capacity()); //20
System.out.println(allocate.limit()); // 8
System.out.println(allocate.position()); //0
System.out.println("--------------------");
System.out.println(allocate.getLong()); //10
System.out.println(allocate.capacity()); //20
System.out.println(allocate.limit()); // 8
System.out.println(allocate.position()); //8
allocate.putLong(10L); //throw exception
}
示意图如下:
从上面示意图能够看出调用方法 flip
的时分会将写入时分回的position指针的值赋给limit一起重置position的值到0的方位。这儿就完成了读写的形式转化。假如再次读取的时分就能够将写入到ByteBuffer的值读取出来。
方法flip首要用于读写形式的切换
Tips: 假如你调用flip方法后读取的数据或许写入的数据超过了limit会有过错抛出
3.2 mark-API
运用代码如下:
public static void main(String[] args) throws Exception{
ByteBuffer allocate = ByteBuffer.allocate(20); //分配一个巨细为20bytes的ByteBuffer
allocate.putLong(10L);
allocate.putInt(1);
allocate.mark();
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//20
System.out.println(allocate.position());//12
System.out.println("-----------------------");
allocate.getLong();
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//20
System.out.println(allocate.position());//20
allocate.reset();
System.out.println("-----------------------");
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//20
System.out.println(allocate.position());//12
}
示意图如下:
从上图能够知道调用 mark
是将position的值赋给mark属性。然后你进行接下来的继续读写操作。当你需要将position恢复到标记字段的时分调用**reset
** 进行恢复。
Tips: 假如你调用mark然后有调用了flip,flip会将mark进行重置。
3.3 compact-API
运用代码实例如下:
public static void main(String[] args) throws Exception{
ByteBuffer allocate = ByteBuffer.allocate(20); //分配一个巨细为20bytes的ByteBuffer
allocate.putLong(10L);
allocate.flip();
allocate.getInt();
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//8
System.out.println(allocate.position());//4
allocate.compact();
System.out.println("----------------------");
System.out.println(allocate.capacity());//20
System.out.println(allocate.limit());//20
System.out.println(allocate.position());//4
}
示意图如下:
从上图能够看出来 compact
的首要效果:用来清楚掉当前position指针之前的数据然后将指针指向limit的方位一起将整个指针往左移动直到替换掉position左面的数据,与此一起还会将limit的值设置为capacity。
4. 总结
ByteBuffer总体运用起来和Netty的ByteBuf对比没有Netty ByteBuf好用。但是对于运用原生的Java NIO的开发来说也是能够的。首要是需要用户自己对读写进行转化等操作,运用起来比较繁琐。但是整个ByteBuffer的完成仍是比较简略的。
我是蚂蚁背大象,文章对你有协助点赞关注我,文章有不正确的当地请您指正留言评论~谢谢! 大家能够Follow我的GitHub mxsm