最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

《跟閃電俠學(xué)Netty》閱讀筆記 - 數(shù)據(jù)載體ByteBuf

2023-08-24 14:19 作者:懶時(shí)小窩  | 我要投稿

Part1《跟閃電俠學(xué)Netty》閱讀筆記 - 數(shù)據(jù)載體 ByteBuf

Part2引言

API設(shè)計(jì)更建議實(shí)戰(zhàn)過程中逐漸了解熟悉掌握,本文記錄基礎(chǔ)設(shè)計(jì)和相關(guān)API,只需要大致了解ByteBuf設(shè)計(jì)思想即可。

Part3思維導(dǎo)圖

https://www.mubucm.com/doc/58ehM7v4PP5

《跟閃電俠學(xué)Netty》 - 數(shù)據(jù)載體ByteBuf.png

Part4基礎(chǔ)結(jié)構(gòu)

整個(gè)ByteBuf的數(shù)據(jù)結(jié)構(gòu)組成如下,整個(gè)設(shè)計(jì)思想有點(diǎn)類似計(jì)算機(jī)如何實(shí)現(xiàn)從北京到上海,那就是一段足夠長的鐵軌,不斷“拆掉”后面的鐵軌放到前面的鐵軌上,這樣實(shí)現(xiàn)火車一直在鐵軌上跑的錯(cuò)覺。

  • 容量上限:maxCapacity

  • 容量:capacity

  • 數(shù)組:

    • 廢棄字節(jié) ?:被丟棄的字節(jié)數(shù)據(jù)無效

    • 可讀字節(jié)(writerIndex -readerIndex)

    • 可寫字節(jié)(capacity - writerIndex)

    • 讀指針 readerIndex :每讀?。╮ead)一個(gè)字節(jié),readerIndex 自增 1

    • 寫指針 writerIndex ?:每寫入(write)一個(gè)字節(jié),writeIndex 自增 1

    • 剩余可用空間

image.png

Part5結(jié)構(gòu)解析


    • 廢棄空間 :被丟棄的字節(jié),數(shù)據(jù)無效

    • 可讀空間 :從ByteBuf讀取出來的數(shù)據(jù)都屬于這部分

    • 可寫空間 :未來所有的寫入都會(huì)寫入到此處

    1. 字節(jié)容器:分為三部分


    • 讀指針

    • 寫指針

    • 總?cè)萘?/p>

    1. 劃分依據(jù):兩個(gè)指針加一個(gè)變量


    • 容量可以在寫滿的時(shí)候擴(kuò)容

    • 如果擴(kuò)容到最大容量就報(bào)錯(cuò)

    1. 最大容量和和容量限制

Part6容量API

實(shí)踐容量API之前,我們先構(gòu)建ByteBuf。

ByteBuf?buffer?=?ByteBufAllocator.DEFAULT.buffer(9,?100);??
print("allocate?ByteBuf(9,100)?=>?{}?\n",?buffer);
//?allocate?ByteBuf(9,100)?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?0,?cap:?9/100)?

1capacity()

表示 ByteBuf 底層占用了多少字節(jié)的內(nèi)存(包括丟棄的字節(jié)、可讀字節(jié)、可寫字節(jié)),不同的底層實(shí)現(xiàn)機(jī)制有不同的計(jì)算方式,后面我們講 ByteBuf 的分類的時(shí)候會(huì)講到。

從案例看出,默認(rèn)創(chuàng)建的方式容量為初始化指定的容量。

print("allocate?ByteBuf(9,100)?capacity?=>?{}?\n",?buffer.capacity());
//?allocate?ByteBuf(9,100)?capacity?=>?9?

2maxCapacity()

表示 ByteBuf 底層最大能夠占用多少字節(jié)的內(nèi)存,當(dāng)向 ByteBuf 中寫數(shù)據(jù)的時(shí)候,如果發(fā)現(xiàn)容量不足,則進(jìn)行擴(kuò)容,直到擴(kuò)容到 maxCapacity,超過這個(gè)數(shù),就拋異常。

從案例可以得知,如果擴(kuò)容到 100 就會(huì)報(bào)錯(cuò)

print("allocate?ByteBuf(9,100)?maxCapacity?=>?{}?\n",?buffer.maxCapacity());??
//?allocate?ByteBuf(9,100)?maxCapacity?=>?100

3readableBytes() 與 isReadable()

readableBytes() 表示 ByteBuf 當(dāng)前可讀的字節(jié)數(shù),它的值等于 writerIndex-readerIndex,如果兩者相等,則不可讀,isReadable() 方法返回 false。

//?readableBytes()?與?isReadable()
print("allocate?ByteBuf(9,100)?isReadable?=>?{}?\n",?buffer.isReadable());??
print("allocate?ByteBuf(9,100)?readableBytes?=>?{}?\n",?buffer.readableBytes());
//????????allocate?ByteBuf(9,100)?isReadable?=>?false??
//????????allocate?ByteBuf(9,100)?readableBytes?=>?0

//?write?方法改變寫指針??
buffer.writeBytes(new?byte[]{1,?2,?3,?4});
//?改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?4,?cap:?9/100)?

//?寫入數(shù)據(jù)之后,重新執(zhí)行readableBytes()?與?isReadable()
print("allocate?ByteBuf(9,100)?isReadable?=>?{}?\n",?buffer.isReadable());
print("allocate?ByteBuf(9,100)?readableBytes?=>?{}?\n",?buffer.readableBytes());
//allocate?ByteBuf(9,100)?isReadable?=>?true?
//allocate?ByteBuf(9,100)?readableBytes?=>?4?


4writableBytes()、 isWritable() 與 maxWritableBytes()

writableBytes() 表示 ByteBuf 當(dāng)前可寫的字節(jié)數(shù),它的值等于 capacity-writerIndex,如果兩者相等,則表示不可寫,isWritable() 返回 false。

注意這個(gè)時(shí)候,并不代表不能往 ByteBuf 中寫數(shù)據(jù)了, 如果發(fā)現(xiàn)往 ByteBuf 中寫數(shù)據(jù)寫不進(jìn)去的話,Netty 會(huì)自動(dòng)擴(kuò)容 ByteBuf,直到擴(kuò)容到底層的內(nèi)存大小為 maxCapacity。

maxWritableBytes() 就表示可寫的最大字節(jié)數(shù),它的值等于 maxCapacity-writerIndex

在初始化構(gòu)建過程中,由于沒有讀寫任何數(shù)據(jù),可以看到他們的值基本和前面計(jì)算的容量是一致的。

ByteBuf?buffer?=?ByteBufAllocator.DEFAULT.buffer(9,?100);?
//?writableBytes()、?isWritable()?與?maxWritableBytes()
print("allocate?ByteBuf(9,100)?writableBytes?=>?{}?\n",?buffer.writableBytes());
print("allocate?ByteBuf(9,100)?isWritable?=>?{}?\n",?buffer.isWritable());
print("allocate?ByteBuf(9,100)?maxWritableBytes?=>?{}?\n",?buffer.maxWritableBytes());
//????????allocate?ByteBuf(9,100)?writableBytes?=>?9
//????????allocate?ByteBuf(9,100)?isWritable?=>?true
//????????allocate?ByteBuf(9,100)?maxWritableBytes?=>?100

Part7讀寫指針相關(guān)的 API

實(shí)踐讀寫指針相關(guān)的 API之前,我們先構(gòu)建初始化ByteBuf。

ByteBuf?buffer?=?ByteBufAllocator.DEFAULT.buffer(9,?100);??
print("allocate?ByteBuf(9,100)?=>?{}?\n",?buffer);??

image.png

5readerIndex() 與 readerIndex(int)

  • readerIndex():返回當(dāng)前的讀指針 readerIndex

  • readerIndex(int):表示設(shè)置讀指針

在沒有寫入任何數(shù)據(jù)的時(shí)候,讀指針為0。

//?readerIndex()?返回當(dāng)前讀指針??
print("allocate?ByteBuf(9,100)?readerIndex?=>?{}?\n",?buffer.readerIndex());??
//?allocate?ByteBuf(9,100)?readerIndex?=>?0

下面的案例說明讀指針不能越過寫指針的界限。

//?嘗試手動(dòng)重定向?yàn)^指針位置??
//?print("allocate?ByteBuf(9,100)?readerIndex(int)?=>?{}?\n",?buffer.readerIndex(2));??
//?readerIndex:?2,?writerIndex:?0?(expected:?0?<=?readerIndex?<=?writerIndex?<=?capacity(9))

我們寫入一些數(shù)據(jù)之后,再進(jìn)行讀指針重定向。

buffer.writeBytes(new?byte[]{1,?2,?3,?4});

//?重定向讀指針??
print("allocate?ByteBuf(9,100)?readerIndex(int)?=>?{}?\n",?buffer.readerIndex(2));??
print("重定向讀指針?之后?(new?byte[]{1,2,3,4})?=>?{}?\n",?buffer);??

//?allocate?ByteBuf(9,100)?readerIndex(int)?=>?PooledUnsafeDirectByteBuf(ridx:?2,?widx:?4,?cap:?9/100)?

//?重定向讀指針?之后?(new?byte[]{1,2,3,4})?=>?PooledUnsafeDirectByteBuf(ridx:?2,?widx:?4,?cap:?9/100)

6writerIndex() 與 writerIndex(int)

  • writeIndex() 表示返回當(dāng)前的寫指針 writerIndex。

  • writeIndex(int) 表示設(shè)置寫指針。

案例以初始化寫入四個(gè)字節(jié)之后作為開始。

//?writeIndex()?與?writeIndex(int)
print("allocate?ByteBuf(9,100)?writerIndex?=>?{}?\n",?buffer.writerIndex());
print("allocate?ByteBuf(9,100)?writerIndex(int)?=>?{}?\n",?buffer.writerIndex(2));
//????????allocate?ByteBuf(9,100)?writerIndex?=>?4
//????????allocate?ByteBuf(9,100)?writerIndex(int)?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?2,?cap:?9/100)

7markReaderIndex() 與 resetReaderIndex()

區(qū)別:

  • markReaderIndex() :表示把當(dāng)前的讀指針保存起來,

  • resetReaderIndex() :表示把當(dāng)前的讀指針恢復(fù)到之前保存的值。

下面兩段代碼是等價(jià)的。

//?代碼片段1
int?readerIndex?=?buffer.readerIndex();

//?…?其他操作
buffer.readerIndex(readerIndex);
//?代碼片段二
//?(不需要自己定義變量,推薦使用)
buffer.markReaderIndex();

//?…?其他操作
//?resetReaderIndex()?可以恢復(fù)到之前狀態(tài)
//?(解析自定義協(xié)議的數(shù)據(jù)包常用)
buffer.resetReaderIndex();?

希望大家多多使用代碼片段二這種方式,不需要自己定義變量,無論 buffer 當(dāng)作參數(shù)傳遞到哪里,調(diào)用 resetReaderIndex() 都可以恢復(fù)到之前的狀態(tài),在解析自定義協(xié)議的數(shù)據(jù)包的時(shí)候非常常見,推薦大家使用這一對(duì) API markWriterIndex() 與 resetWriterIndex() 這一對(duì) API 的作用與上述一對(duì) API 類似

Part8讀寫API

實(shí)踐讀寫API之前,我們先構(gòu)建ByteBuf。

ByteBuf?buffer?=?ByteBufAllocator.DEFAULT.buffer(9,?100);??
print("allocate?ByteBuf(9,100)?=>?{}?\n",?buffer);??

上面的代碼

8writeBytes(byte[] src) 與 buffer.readBytes(byte[] dst)

writeBytes() 表示把字節(jié)數(shù)組 src 里面的數(shù)據(jù)全部寫到 ByteBuf。注意此方法執(zhí)行之后,會(huì)移動(dòng)前面介紹的 writeIndex 寫指針。

//?write?方法改變寫指針??
buffer.writeBytes(new?byte[]{1,?2,?3,?4});??
print("改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?{}?\n",?buffer);??
//?改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?4,?cap:?9/100)

readBytes() 指的是把 ByteBuf 里面的數(shù)據(jù)全部讀取到 dst。

//只有read方法改變指針??
byte[]?bytes?=?new?byte[buffer.readableBytes()];??
buffer.readBytes(bytes);??
??
print("bytes?內(nèi)容?=>?{}",?bytes);??
//?bytes?內(nèi)容?=>??????

這里 dst 字節(jié)數(shù)組的大小通常等于 readableBytes(),而 src 字節(jié)數(shù)組大小的長度通常小于等于writableBytes()。

9writeByte(byte b) 與 buffer.readByte()

writeByte() 表示往 ByteBuf 中寫一個(gè)字節(jié),而 buffer.readByte() 表示從 ByteBuf 中讀取一個(gè)字節(jié),類似的 API 還有 writeBoolean()、writeChar()、writeShort()、writeInt()、writeLong()、writeFloat()、writeDouble() 與 readBoolean()、readChar()、readShort()、readInt()、readLong()、readFloat()、readDouble() 這里就不一一贅述。

//?write?方法改變寫指針??
buffer.writeBytes(new?byte[]{1,?2,?3,?4});??
print("改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?{}?\n",?buffer);??
//?改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?4,?cap:?9/100)buffer.writeByte(5);??
print("改變寫指針?buffer.writeByte(5)?=>?{}?\n",?buffer);??
//?改變寫指針?buffer.writeByte(5)?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?5,?cap:?9/100)

getBytes、getByte() 與 setBytes()、setByte() 系列,唯一的區(qū)別就是 get/set 不會(huì)改變讀寫指針,而 read/write 會(huì)改變讀寫指針。

//只有read方法改變指針??
byte[]?bytes?=?new?byte[buffer.readableBytes()];??
buffer.readBytes(bytes);
print("buffer.readBytes(bytes)?=>?{}\n",?buffer);??
//?buffer.readBytes(bytes)?=>?PooledUnsafeDirectByteBuf(ridx:?10,?widx:?10,?cap:?16/100)

10release() 與 retain()

由于 Netty 使用了堆外內(nèi)存,而堆外內(nèi)存是不被 jvm 直接管理的,也就是說申請(qǐng)到的內(nèi)存無法被垃圾回收器直接回收,所以需要我們手動(dòng)回收。

Netty 的 ByteBuf 是通過引用計(jì)數(shù)的方式管理的,如果一個(gè) ByteBuf 沒有地方被引用到,就需要回收底層內(nèi)存。

默認(rèn)情況下,當(dāng)創(chuàng)建完一個(gè) ByteBuf,它的引用為1,然后每次調(diào)用 retain() 方法, 它的引用就加一, release() 方法原理是將引用計(jì)數(shù)減一,減完之后如果發(fā)現(xiàn)引用計(jì)數(shù)為0,則直接回收 ByteBuf 底層的內(nèi)存。

Part9Test

最后是簡單測(cè)試程序整合前面的API案例。

public?class?ByteBufTest?{
????public?static?void?main(String[]?args)?{
????????ByteBuf?buffer?=?ByteBufAllocator.DEFAULT.buffer(9,?100);

????????print("allocate?ByteBuf(9,?100)",?buffer);

????????//?write?方法改變寫指針,寫完之后寫指針未到?capacity?的時(shí)候,buffer?仍然可寫
????????buffer.writeBytes(new?byte[]{1,?2,?3,?4});
????????print("writeBytes(1,2,3,4)",?buffer);

????????//?write?方法改變寫指針,寫完之后寫指針未到?capacity?的時(shí)候,buffer?仍然可寫,?寫完?int?類型之后,寫指針增加4
????????buffer.writeInt(12);
????????print("writeInt(12)",?buffer);

????????//?write?方法改變寫指針,?寫完之后寫指針等于?capacity?的時(shí)候,buffer?不可寫
????????buffer.writeBytes(new?byte[]{5});
????????print("writeBytes(5)",?buffer);

????????//?write?方法改變寫指針,寫的時(shí)候發(fā)現(xiàn)?buffer?不可寫則開始擴(kuò)容,擴(kuò)容之后?capacity?隨即改變
????????buffer.writeBytes(new?byte[]{6});
????????print("writeBytes(6)",?buffer);

????????//?get?方法不改變讀寫指針
????????System.out.println("getByte(3)?return:?"?+?buffer.getByte(3));
????????System.out.println("getShort(3)?return:?"?+?buffer.getShort(3));
????????System.out.println("getInt(3)?return:?"?+?buffer.getInt(3));
????????print("getByte()",?buffer);


????????//?set?方法不改變讀寫指針
????????buffer.setByte(buffer.readableBytes()?+?1,?0);
????????print("setByte()",?buffer);

????????//?read?方法改變讀指針
????????byte[]?dst?=?new?byte[buffer.readableBytes()];
????????buffer.readBytes(dst);
????????print("readBytes("?+?dst.length?+?")",?buffer);

????}

????private?static?void?print(String?action,?ByteBuf?buffer)?{
????????System.out.println("after?==========="?+?action?+?"============");
????????System.out.println("capacity():?"?+?buffer.capacity());
????????System.out.println("maxCapacity():?"?+?buffer.maxCapacity());
????????System.out.println("readerIndex():?"?+?buffer.readerIndex());
????????System.out.println("readableBytes():?"?+?buffer.readableBytes());
????????System.out.println("isReadable():?"?+?buffer.isReadable());
????????System.out.println("writerIndex():?"?+?buffer.writerIndex());
????????System.out.println("writableBytes():?"?+?buffer.writableBytes());
????????System.out.println("isWritable():?"?+?buffer.isWritable());
????????System.out.println("maxWritableBytes():?"?+?buffer.maxWritableBytes());
????????System.out.println();
????}
}

最后是個(gè)人的實(shí)驗(yàn)Test類。

??
/**??
?*?byteBuf?的API測(cè)試??
?*/
??
public?class?ByteBufTest?{??
??
????public?static?void?main(String[]?args)?{??
????????//?9?代表初始容量,?100代表最大容量??
????????ByteBuf?buffer?=?ByteBufAllocator.DEFAULT.buffer(9,?100);??
????????print("allocate?ByteBuf(9,100)?=>?{}?\n",?buffer);??
????????//allocate?ByteBuf(9,100)?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?0,?cap:?9/100)??
??
????????//?write?方法改變寫指針??
????????buffer.writeBytes(new?byte[]{1,?2,?3,?4});??
????????print("改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?{}?\n",?buffer);??
????????//?改變寫指針?writeBytes(new?byte[]{1,2,3,4})?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?4,?cap:?9/100)??
????????//?write?改變寫指針,如果沒有到達(dá)?capacity?依然可以寫入,寫入?int?之后寫指針增加4??
????????buffer.writeInt(12);??
????????print("buffer.writeInt(12)?=>?{}\n",?buffer);??
????????//?buffer.writeInt(12)?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?8,?cap:?9/100)??
??
????????//?繼續(xù)改變寫指針,當(dāng)前寫入等于??initialCapacity?這個(gè)初始值之后將不能繼續(xù)寫入??
????????buffer.writeBytes(new?byte[]{5});??
????????print("writeBytes(new?byte[]{5})?=>?{}\n",?buffer);??
????????//?writeBytes(new?byte[]{5})?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?9,?cap:?9/100)??
??
????????//?繼續(xù)寫入指針,此時(shí)發(fā)現(xiàn)?已經(jīng)超過?initialCapacity?的值,此時(shí)會(huì)進(jìn)行擴(kuò)容??
????????buffer.writeBytes(new?byte[]{6});??
????????print("writeBytes(new?byte[]{6})?=>?{}\n",?buffer);??
????????//?writeBytes(new?byte[]{6})?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?10,?cap:?16/100)??
??
????????//?get?方法調(diào)用之后不改變讀指針??
????????print("getByte(3)?return?=>?{}\n",?buffer.getByte(3));??
????????print("getShort(3)?return?=>?{}\n",?buffer.getShort(3));??
????????print("getInt(3)?return?=>?{}\n",?buffer.getInt(3));??
????????print("getChar(3)?return?=>?{}\n",?buffer.getChar(3));??
????????/*??
???????getByte(3)?return?=>?4????????getShort(3)?return?=>?1024????????getInt(3)?return?=>?67108864????????getChar(3)?return?=>????
????????*?*/
??
????????//?set?方法不改變讀寫指針??
????????buffer.setByte(buffer.readableBytes()?+?1,?0);??
????????print("setByte(buffer.readableBytes()?+?1,?0)?=>?{}\n",?buffer);??
????????//?setByte(buffer.readableBytes()?+?1,?0)?=>?PooledUnsafeDirectByteBuf(ridx:?0,?widx:?10,?cap:?16/100)??
??
????????//只有read方法改變指針??
????????byte[]?bytes?=?new?byte[buffer.readableBytes()];??
????????buffer.readBytes(bytes);??
??
????????print("buffer.readBytes(bytes)?=>?{}\n",?buffer);??
????????//?buffer.readBytes(bytes)?=>?PooledUnsafeDirectByteBuf(ridx:?10,?widx:?10,?cap:?16/100)??
????????print("buffer.readBytes(readBuffer);?=>?{}\n",?buffer);??
??
????????ByteBuf?readBuffer?=?ByteBufAllocator.DEFAULT.buffer(6,?6);??
????????//?原始writeIndex要有足夠空間可讀??
//????????buffer.writeBytes(new?byte[]{5,1,1,1,1,1,1,1});??
??
//????????buffer.writeBytes(new?byte[]{5});??
????????//??readerIndex(10)?+?length(6)?exceeds?writerIndex(11):?PooledUnsafeDirectByteBuf(ridx:?10,?widx:?11,?cap:?16/100)????????buffer.readBytes(readBuffer);??
??
????????System.err.println(readBuffer.readableBytes());??
??
//????????buffer.readBytes(readBuffer);??
????????//?readerIndex(10)?+?length(9)?exceeds?writerIndex(10):?PooledUnsafeDirectByteBuf(ridx:?10,?widx:?10,?cap:?16/100)??
????}??
??
??
}

Part10寫在最后

比較簡單的一個(gè)章節(jié),主要介紹ByteBuf在Java中的使用,整個(gè)使用過程簡單易懂十分清晰。


《跟閃電俠學(xué)Netty》閱讀筆記 - 數(shù)據(jù)載體ByteBuf的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
聂拉木县| 沽源县| 榆中县| 祁阳县| 南宁市| 临洮县| 乡城县| 乡宁县| 贵定县| 鹰潭市| 哈密市| 乌兰浩特市| 泗阳县| 沁源县| 襄城县| 施甸县| 长宁区| 伽师县| 巫溪县| 花莲县| 无极县| 酉阳| 麻栗坡县| 仙桃市| 镇宁| 滁州市| 石棉县| 福安市| 乐山市| 秭归县| 延边| 孟村| 阿克苏市| 三都| 保康县| 北辰区| 盘山县| 日喀则市| 东阳市| 商丘市| 渭南市|