ByteBuf动态扩容机制

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值