package com.demo.study.socket.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.Arrays;
public class ByteBufDemo {
public static void main(String[] args) {
// 1.初始化bytebuf
ByteBuf buffer = Unpooled.buffer(10);
System.out.println("原始buffer信息:" + buffer.toString());
System.out.println("1.原始buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
// 2.写入数据
byte[] byte1 = {1, 2, 3, 4, 5};
buffer.writeBytes(byte1);
System.out.println("写入的数据为:" + Arrays.toString(byte1));
System.out.println("写入后buffer信息:" + buffer.toString());
System.out.println("2.写入后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
// 写入五个数据之后,读指针还在0,写指针已经到了5了
// 3.读出一些数据
byte b1 = buffer.readByte();
byte b2 = buffer.readByte();
System.out.println("读出的数据为:" + Arrays.toString(new byte[]{b1, b2}));
System.out.println("读取一些数据后buffer信息:" + buffer.toString());
System.out.println("3.读取一些数据后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
//读出前面两个数据之后,读指针移动到2,写指针还在5
// 4.将读取过的数据丢弃
buffer.discardReadBytes();
System.out.println("数据丢弃后buffer信息:" + buffer.toString());
System.out.println("4.数据丢弃后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
// 丢弃读的两个数据之后,读指针回到0,写指针向前移动两个,变成3
// 4.数据丢弃后buffer数据信息:[3, 4, 5, 4, 5, 0, 0, 0, 0, 0]
// 5.清空读写指针
buffer.clear();
System.out.println("数据丢弃后buffer信息:" + buffer.toString());
System.out.println("5.数据丢弃后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
// 读写指针都归零
// 5.数据丢弃后buffer数据信息:[3, 4, 5, 4, 5, 0, 0, 0, 0, 0]
// 6.再次写入一段数据
byte[] byte2 = {7, 8, 9};
buffer.writeBytes(byte2);
System.out.println("写入的数据为:" + Arrays.toString(byte2));
System.out.println("写入后buffer信息:" + buffer.toString());
System.out.println("6.写入后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
// 写入三字节数据,写指针移动到3,读指针还是0
// 会将之前缓冲区里面的数据覆盖
// 6.写入后buffer数据信息:[7, 8, 9, 4, 5, 0, 0, 0, 0, 0]
// 7.将buffer清零
buffer.setZero(0, buffer.capacity());
System.out.println("清零后buffer信息:" + buffer.toString());
System.out.println("7.清零后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
//将buffer清零之后,写指针还是在3,读指针还是在0,数据都是0 了
// 7.清零后buffer数据信息:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
// 8.再次写入数据,数据长度比buffer容量大
byte[] byte3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
buffer.writeBytes(byte3);
System.out.println("写入的数据为:" + Arrays.toString(byte3));
System.out.println("写入后buffer信息:" + buffer.toString());
System.out.println("8.写入后buffer数据信息:" + Arrays.toString(buffer.array()) + "\n");
// 写入11个字节,超过缓冲区的容量,自动扩容,写指针从第三个开始写,写道第14个,容量扩容为64
// 写入后buffer信息:UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 0, widx: 14, cap: 64)
// 8.写入后buffer数据信息:[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
}
第八步,向容量为10 的ByteBuf中写入11字节,查看writeBytes()方法。
首先检查是否有足够的可写空间,是否需要扩容。
final void ensureWritable0(int minWritableBytes) {
ensureAccessible();//判断buf是否可用
if (minWritableBytes <= writableBytes()) {//判断最小可写长度是否大于当前待写入的长度,
return;
}
if (checkBounds) {
if (minWritableBytes > maxCapacity - writerIndex) {
throw new IndexOutOfBoundsException(String.format(
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
writerIndex, minWritableBytes, maxCapacity, this));
}
}
// Normalize the current capacity to the power of 2.扩容计算,当前容量扩容至的2次方幂大小
int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);
// Adjust to the new capacity.设置新容量
capacity(newCapacity);
}
calculateNewCapacity是扩容算法
public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
if (minNewCapacity < 0) {//最小需要的容量,当前已经写入的加上需要写入的容量大小
throw new IllegalArgumentException("minNewCapacity: " + minNewCapacity + " (expected: 0+)");
}
if (minNewCapacity > maxCapacity) {//最小需要的容量是否大于int的最大值
throw new IllegalArgumentException(String.format(
"minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
minNewCapacity, maxCapacity));
}
final int threshold = CALCULATE_THRESHOLD; // 4 MiB page 阈值4兆
if (minNewCapacity == threshold) {//如果最小需要的容量等于阈值,就返回阈值
return threshold;
}
// If over threshold, do not double but just increase by threshold.
if (minNewCapacity > threshold) {//如果大于阈值,就按照下面的返回
int newCapacity = minNewCapacity / threshold * threshold;
if (newCapacity > maxCapacity - threshold) {
newCapacity = maxCapacity;
} else {
newCapacity += threshold;
}
return newCapacity;
}
// Not over threshold. Double up to 4 MiB, starting from 64.
//不超过阈值,就从64字节开始每次增加2倍,直至符合要求(新容量大于最小需要的容量)
int newCapacity = 64;
while (newCapacity < minNewCapacity) {
newCapacity <<= 1;
}
return Math.min(newCapacity, maxCapacity);
}
+-------------------+------------------+------------------+
| discardable bytes | readable bytes | writable bytes |
| | (CONTENT) | |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity