搞懂了这个原理,你比别人会多个面试机会

112 阅读3分钟

大家好,给大家先做个自我介绍
我是码上代码,大家可以叫我码哥
我也是一个普通本科毕业的最普通学生,我相信大部分程序员或者想从事程序员行业的都是普通家庭的孩子,所以我也是靠自己的努力,从毕业入职到一家传统企业,到跳槽未尝败绩,现在在一家某互联网行业巨头公司工作,希望可以通过自己的分享对大家有一些帮助
跟随我的专栏学习,可以省去你很多去培训的费用或者网上找资料的时间,节省你的大部分时间成本,让你更加快速成为面试收割机,年度最佳员工

我为大家准备了16个技术专栏带领大家一起学习

《亿级流量分布式系统实战》

《BAT大厂面试必问系列》

《技术杂谈》

《零基础带你学java教程专栏》

《带你学springCloud专栏》

《带你学SpringCloud源码专栏》

《带你学分布式系统专栏》

《带你学云原生专栏》

《带你学springboot源码》

《带你学netty原理与实战专栏》

《带你学Elasticsearch专栏》

《带你学mysql专栏》

《带你学JVM原理专栏》

《带你学Redis原理专栏》

《带你学java进阶专栏》

《带你学大数据专栏》


前言

在网络传输过程中,字节是最基本也是最小的单元。JAVA NIO有提供一个ByteBuffer容器去装载这些数据,但是用起来会有点复杂,经常要在读写间进行切换以及不支持动态扩展等等。而netty为我们提供了一个ByteBuf组件,功能是很强大的,本文主要对ByteBuf进行一些讲解,中间会穿插着和ByteBuffer进行对比。

优势

ByteBuf与ByteBuffer的相比的优势:
读和写用不同的索引。
读和写可以随意的切换,不需要调用flip()方法。
容量能够被动态扩展,和StringBuilder一样。
用其内置的复合缓冲区可实现透明的零拷贝。
支持方法链。
支持引用计数。count == 0,release。
支持池。

读写索引

ByteBuffer读写同用position索引,利用flip()方法切换读写模式,而ByteBuf读写分不同的索引,读用readIndex,写用writeIndex,这样可以更加方便我们进行操作,省去了flip这一步骤。ByteBuffer与ByteBuf两种读写模型会在下面用图解形式给大家进行说明。
在这里插入图片描述
在这里插入图片描述

动态扩展

ByteBuffer是不支持动态扩展的,给定一个具体的capacity,一旦put进去的数据超过其容量,就会抛出java.nio.BufferOverflowException异常,而ByteBuf完美的解决了这一问题,支持动态扩展其容量。

零拷贝

netty提供了CompositeByteBuf类实现零拷贝。大多数情况下,在进行网络数据传输时我们会将消息分为消息头head和消息体body

这里通过CompositeByteBuf 对象将headerBuf 与bodyBuf组合到了一起,也得到了完整的消息体,但是并未进行内存上的拷贝。可以注意下我在上面代码段中进行的buf.toString()方法的调用,得出来的结果是:指向的还是原来分配的空间地址,也就证明了零拷贝的观点。

支持引用计数

引用计数器实现的原理并不复杂,仅仅只是涉及到一个指定对象的活动引用,对象被初始化后引用计数值为1。只要引用计数大于0,这个对象就不会被释放,当引用计数减到为0时,这个实例就会被释放,被释放的对象不应该再被使用。

支持池

Netty对ByteBuf的分配提供了池支持,具体的类是PooledByteBufAllocator。用这个分配器去分配ByteBuf可以提升性能以及减少内存碎片。Netty中默认用PooledByteBufAllocator当做ByteBuf的分配器。PooledByteBufAllocator对象可以从Channel中或者绑定了Channel的ChannelHandlerContext中去获取到。