ByteBuf--Netty的數(shù)據(jù)容器

      網(wǎng)友投稿 881 2025-04-03

      ByteBuf--Netty的數(shù)據(jù)容器

      網(wǎng)絡(luò)傳輸?shù)幕締挝皇亲止?jié),在Java NIO中,JDK提供了Buffer接口,以及其相關(guān)的實(shí)現(xiàn)作為NIO操作 數(shù)據(jù)的容器,如ByteBuffer等等。 而Netty為了解決Buffer原生接口的復(fù)雜操作提供了ByteBuf, ByteBuf是一個(gè)很好的經(jīng)過優(yōu)化過的數(shù)據(jù)容器,我們可以將字節(jié)數(shù)據(jù)添加到ByteBuf中或從ByteBuf中獲取數(shù)據(jù), 相比于原生Buffer,ByteBuf更加靈活和易用。

      Netty的數(shù)據(jù)處理主要通過兩個(gè)API提供:

      abstract class ByteBuf

      interface ByteBufHolder

      使用ByteBuf API能夠給我們帶來良好的編碼體驗(yàn),如

      正常情況下,ByteBuf比ByteBuffer的性能更好;

      實(shí)現(xiàn)了ReferenceCounted引用計(jì)數(shù)接口,優(yōu)化了內(nèi)存的使用;

      容量可以動(dòng)態(tài)增長,如StringBuilder之于String;

      在讀和寫這兩種模式切換時(shí),無需像ByteBuffer一樣調(diào)用flip方法,更易于操作;

      ...

      ByteBuf還有很多好處,上面列舉的只是一部分,其他優(yōu)點(diǎn)就需要各位同學(xué)慢慢了解了。

      ByteBuf實(shí)現(xiàn)

      ByteBuf維護(hù)了兩個(gè)不同的索引:一個(gè)是用于讀取的readerIndex , 一個(gè)是用于寫入的writerIndex。 當(dāng)我們寫入字節(jié)到ByteBuf后,writerIndex增加,開始讀取字節(jié)后,readerIndex開始增加。讀取字節(jié)直到 readerIndex和writerIndex到達(dá)同一位置(已經(jīng)讀取到末尾了),ByteBuf就變?yōu)椴豢勺x。 這就好比當(dāng)我們訪問數(shù)組時(shí),超出了它的范圍時(shí),程序會(huì)拋出IndexOutOfBoundException。

      當(dāng)我們調(diào)用ByteBuf以read或write開頭的方法時(shí),將會(huì)增加這個(gè)ByteBuf的讀索引或?qū)懰饕T如set或get 的方法則不會(huì)改變索引。

      我們可以指定ByteBuf的最大容量,如果對ByteBuf的寫入操作導(dǎo)致writerIndex超出了最大容量,那么程序?qū)?huì) 拋出一個(gè)異常,ByteBuf的最大容量是Integer.MAX_VALUE。

      ByteBuf大致的結(jié)構(gòu)和狀態(tài):

      ByteBuf使用模式

      ByteBuf--Netty的數(shù)據(jù)容器

      ByteBuf有多種使用模式,我們可以根據(jù)需求構(gòu)建不同使用模式的ByteBuf。

      堆緩沖區(qū)(HeapByteBuf): 最常用的ByteBuf模式是將數(shù)據(jù)存儲(chǔ)在JVM的堆空間中,實(shí)際上是通過數(shù)組存儲(chǔ)數(shù)據(jù), 所以這種模式被稱為支撐數(shù)組(Backing Array)。它可以在沒有使用池化的情況下快速分配和釋放, 適合用于有遺留數(shù)據(jù)需要處理的情況。

      直接緩沖區(qū)(DirectByteBuf): 在Java中,我們創(chuàng)建的對象大部分都是存儲(chǔ)在堆區(qū)之中的,但這不是絕對的,在NIO的API中, 允許Buffer分配直接內(nèi)存,即操作系統(tǒng)的內(nèi)存,這樣做的好處非常明顯: 前面在傳輸章節(jié)介紹過的零拷貝技術(shù)的 特點(diǎn)之一就是規(guī)避了多次IO拷貝,而現(xiàn)在數(shù)據(jù)直接就在直接內(nèi)存中,而不是在JVM應(yīng)用進(jìn)程中,這不僅減少了拷貝次數(shù), 是否還意味著減少了用戶態(tài)與內(nèi)核態(tài)的上下文切換呢? 直接緩沖區(qū)的缺點(diǎn)也比較明顯: 直接內(nèi)存的分配和釋放都較為昂貴,而且因?yàn)橹苯?緩沖區(qū)的數(shù)據(jù)不是在堆區(qū)的,所以我們在某些時(shí)候可能需要將直接緩沖區(qū)的數(shù)據(jù)先拷貝一個(gè)副本到堆區(qū), 再對這個(gè)副本進(jìn)行操作。 與支撐數(shù)組相比,直接緩沖區(qū)的工作可能更多,所以如果事先知道數(shù)據(jù)會(huì)作為 一個(gè)數(shù)組來被訪問,那么我們應(yīng)該使用堆內(nèi)存。

      復(fù)合緩沖區(qū)(CompositeByteBuf): CompositeByteBuf為多個(gè)ByteBuf提供了一個(gè)聚合視圖, 我們可以根據(jù)需要,向CompositeByteBuf中添加或刪除ByteBuf實(shí)例,所以CompositeByteBuf中可能 同時(shí)包含直接緩沖區(qū)模式和堆緩沖區(qū)模式的ByteBuf。對于CompositeByteBuf的hasArray方法,?如果CompositeByteBuf中只有一個(gè)ByteBuf實(shí)例,那么CompositeByteBuf的hasArray方法 將直接返回這唯一一個(gè)ByteBuf的hasArray方法的結(jié)果,否則返回false。?除此之外,CompositeByteBuf還提供了許多附加的功能,可以查看Netty的文檔學(xué)習(xí)。

      字節(jié)級別的操作

      除了普通的讀寫操作,ByteBuf還提供了修改數(shù)據(jù)的方法。

      如數(shù)組的索引訪問一樣,ByteBuf的索引訪問也是從零開始的,第一個(gè)字節(jié)的索引是0,最后一個(gè)字節(jié)的索引總是 capacity - 1:

      注意:使用getByte方式訪問,既不會(huì)改變r(jià)eaderIndex,也不會(huì)改變writerIndex。

      JDK的ByteBuffer只有一個(gè)索引position,所以當(dāng)ByteBuffer在讀和寫模式之間切換時(shí),需要使用flip方法。 而ByteBuf同時(shí)具有讀索引和寫索引,則無需切換模式,在ByteBuf內(nèi)部,其索引滿足:

      0 <= readerIndex <= writerIndex <= capacity

      這樣的規(guī)律,當(dāng)使用readerIndex讀取字節(jié),或使用writerIndex寫入字節(jié)時(shí),ByteBuf內(nèi)部的分段大致如下:

      上圖介紹了在ByteBuf內(nèi)部大致有3個(gè)分段,接下來我們就詳細(xì)的介紹下這三個(gè)分段。

      上圖中,當(dāng)readerIndex讀取一部分字節(jié)后,之前讀過的字節(jié)就屬于已讀字節(jié),可以被丟棄了,通過調(diào)用 ByteBuf的discardReadBytes方法我們可以丟棄這個(gè)分段,丟棄這個(gè)分段實(shí)際上是刪除這個(gè)分段的已讀字節(jié), 然后回收這部分空間:

      ByteBuf的可讀字節(jié)分段存儲(chǔ)了尚未讀取的字節(jié),我們可以使用readBytes等方法來讀取這部分?jǐn)?shù)據(jù),如果我們讀取 的范圍超過了可讀字節(jié)分段,那么ByteBuf會(huì)拋出IndexOutOfBoundsException異常,所以在讀取數(shù)據(jù)之前,我們 需要使用isReadable方法判斷是否仍然有可讀字節(jié)分段。

      可寫字節(jié)分段即沒有被寫入數(shù)據(jù)的區(qū)域,我們可以使用writeBytes等方法向可寫字節(jié)分段寫入數(shù)據(jù),如果我們寫入 的字節(jié)超過了ByteBuf的容量,那么ByteBuf也會(huì)拋出IndexOutOfBoundsException異常。

      我們可以通過markReaderIndex,markWriterIndex方法來標(biāo)記當(dāng)前readerIndex和writerIndex的位置, 然后使用resetReaderIndex,resetWriterIndex方法來將readerIndex和writerIndex重置為之前標(biāo)記過的 位置。

      我們還可以使用clear方法來將readerIndex和writerIndex重置為0,但是clear方法并不會(huì)清空ByteBuf的 內(nèi)容,下面clear方法的實(shí)現(xiàn):

      由于調(diào)用clear后,數(shù)據(jù)并沒有被清空,但整個(gè)ByteBuf仍然是可寫的,這比discardReadBytes輕量的多, DiscardReadBytes還要回收已讀字節(jié)空間。

      在ByteBuf中,有多種可以確定值的索引的方法,最簡單的方法是使用ByteBuf的indexOf方法。 較為復(fù)雜的查找可以通過ByteBuf的forEachByte方法,forEachByte方法所需的參數(shù)是ByteProcessor, 但我們無需去實(shí)現(xiàn)ByteProcessor,因?yàn)锽yteProcessor已經(jīng)為我們定義好了兩個(gè)易用的實(shí)現(xiàn)。

      API Java

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:表格如何拆分為2個(gè)窗口對比查看(兩個(gè)表格怎么分成兩個(gè)窗口)
      下一篇:業(yè)務(wù)甘特圖
      相關(guān)文章
      亚洲午夜电影在线观看高清| 亚洲一区二区三区电影| 亚洲人成网网址在线看| 国产AV无码专区亚洲AWWW| 亚洲国产精品丝袜在线观看| 亚洲香蕉久久一区二区 | 亚洲国产精品日韩专区AV| 国产精品亚洲专区在线播放| 怡红院亚洲红怡院在线观看| 亚洲成a∧人片在线观看无码 | 亚洲色精品aⅴ一区区三区| 国产成人精品久久亚洲| 亚洲国产精品一区二区三区久久| 国产在亚洲线视频观看| 亚洲欧洲久久av| 国产亚洲一区二区三区在线不卡 | 久久久久亚洲AV综合波多野结衣 | 中文字幕亚洲综合小综合在线| 中文字幕亚洲综合小综合在线 | 亚洲综合色一区二区三区| 亚洲人av高清无码| 久久久久亚洲精品无码网址色欲| 成人婷婷网色偷偷亚洲男人的天堂 | 亚洲国产日韩在线成人蜜芽 | 亚洲精品无码99在线观看 | 在线亚洲精品福利网址导航| 国产亚洲精品自在久久| 亚洲成人中文字幕| 亚洲经典在线中文字幕| 国产亚洲国产bv网站在线 | 亚洲精品免费观看| 亚洲一级毛片免观看| 亚洲小说图区综合在线| 亚洲GV天堂GV无码男同| 亚洲七七久久精品中文国产| 国产精品亚洲片在线观看不卡| 亚洲va在线va天堂va四虎 | 亚洲精品456播放| 国产av天堂亚洲国产av天堂| 久久精品亚洲一区二区三区浴池| 亚洲系列中文字幕|