【Netty学习】九、ByteBuf浅层复制的高级使用方式

九、ByteBuf浅层复制的高级使用方式

浅层复制是一种非常重要的操作。可以很大程度地避免内存复制。这一点对于大规模消息通信来说是非常重要的。
ByteBuf的浅层复制分为两种,有切片(slice)浅层复制和整体(duplicate)浅层复制

slice切片浅层复制

ByteBuf的slice方法可以获取到一个ByteBuf的一个切片。一个ByteBuf可以进行多次的切片浅层复制;多次切片后的ByteBuf对象可以共享一个存储区域
示例:

        package com.crazymakercircle.netty.bytebuf;
        //....
        public class SliceTest {
            @Test
            public  void testSlice() {
              ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);
              print("动作:分配ByteBuf(9, 100)", buffer);
              buffer.writeBytes(new byte[]{1, 2, 3, 4});
              print("动作:写入4个字节 (1,2,3,4)", buffer);
              ByteBuf slice = buffer.slice();
              print("动作:切片slice", slice);
            }
        }

在上面代码中,输出了源ByteBuf和调用slice方法后的切片ByteBuf的三组属性值,运行结果如下:

        //…篇幅原因,省略了ByteBuf刚分配后的属性值输出
        [main|SliceTest:print]:after ===========动作:写入4个字节
    (1,2,3,4)============
        [main|SliceTest:print]:1.0 isReadable(): true
        [main|SliceTest:print]:1.1 readerIndex(): 0
        [main|SliceTest:print]:1.2 readableBytes(): 4
        [main|SliceTest:print]:2.0 isWritable(): true
        [main|SliceTest:print]:2.1 writerIndex(): 4
        [main|SliceTest:print]:2.2 writableBytes(): 5
        [main|SliceTest:print]:3.0 capacity(): 9
        [main|SliceTest:print]:3.1 maxCapacity(): 100
        [main|SliceTest:print]:3.2 maxWritableBytes(): 96
        [main|SliceTest:print]:after ===========动作:切片slice============
        [main|SliceTest:print]:1.0 isReadable(): true
        [main|SliceTest:print]:1.1 readerIndex(): 0
        [main|SliceTest:print]:1.2 readableBytes(): 4
        [main|SliceTest:print]:2.0 isWritable(): false
        [main|SliceTest:print]:2.1 writerIndex(): 4
        [main|SliceTest:print]:2.2 writableBytes(): 0
        [main|SliceTest:print]:3.0 capacity(): 4
        [main|SliceTest:print]:3.1 maxCapacity(): 4
        [main|SliceTest:print]:3.2 maxWritableBytes(): 0

调用slice()方法后,返回的切片是一个新的ByteBuf对象,该对象的几个重要属性值,大致如下:
· readerIndex(读指针)的值为0。
· writerIndex(写指针)的值为源Bytebuf的readableBytes()可读字节数。
· maxCapacity(最大容量)的值为源Bytebuf的readableBytes( )可读字节数。

切片后的新Bytebuf有两个特点:
· 切片不可以写入,原因是:maxCapacity与writerIndex值相同。
· 切片和源ByteBuf的可读字节数相同,原因是:切片后的可读字节数为自己的属性writerIndex - readerIndex,也就是源ByteBuf的readableBytes()-0。

切片后的新ByteBuf和源ByteBuf的关联性:
· 切片不会复制源ByteBuf的底层数据,底层数组和源ByteBuf的底层数组是同一个。
· 切片不会改变源ByteBuf的引用计数。
从根本上说,slice()无参数方法所生成的切片就是源ByteBuf可读部分的浅层复制。

duplicate整体浅层复制

和slice切片不同,duplicate() 返回的是源ByteBuf的整个对象的一个浅层复制,包括如下内容:
· duplicate的读写指针、最大容量值,与源ByteBuf的读写指针相同。
· duplicate() 不会改变源ByteBuf的引用计数。
· duplicate() 不会复制源ByteBuf的底层数据。
duplicate() 和slice() 方法都是浅层复制。不同的是,slice()方法是切取一段的浅层复制,而duplicate( )是整体的浅层复制。

浅层复制的问题

浅层复制方法不会实际去复制数据,也不会改变ByteBuf的引用计数,这就会导致一个问题:在源ByteBuf调用release() 之后,一旦引用计数为零,就变得不能访问了;在这种场景下,源ByteBuf的所有浅层复制实例也不能进行读写了;如果强行对浅层复制实例进行读写,则会报错。
因此,在调用浅层复制实例时,可以通过调用一次retain() 方法来增加引用,表示它们对应的底层内存多了一次引用,引用计数为2。在浅层复制实例用完后,需要调用两次release()方法,将引用计数减一,这样就不影响源ByteBuf的内存释放。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值