欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

又又叕出BUG啦!理智分析Java NIO的ByteBuffer到底有多難用

 更新時間:2021年06月04日 09:27:47   作者:JavaEdge.  
網(wǎng)絡(luò)數(shù)據(jù)的基本單位永遠(yuǎn)是byte,Java NIO提供ByteBuffer作為字節(jié)的容器,但該類過于復(fù)雜,有點(diǎn)難用.本篇文章就帶大家簡單了解一下 ,需要的朋友可以參考下

一、前言

ByteBuf是Netty當(dāng)中的最重要的工具類,它與JDK的ByteBuffer原理基本上相同,也分為堆內(nèi)與堆外倆種類型,但是ByteBuf做了極大的優(yōu)化,具有更簡單的API,更多的工具方法和優(yōu)秀的內(nèi)存池設(shè)計。

二、API

Netty 的數(shù)據(jù)處理 API 通過兩個組件暴露——抽象類ByteBuf 和 接口 ByteBufHolder。

ByteBuf API 的優(yōu)點(diǎn):

  • 它可以被用戶自定義的緩沖區(qū)類型擴(kuò)展
  • 通過內(nèi)置的復(fù)合緩沖區(qū)類型實現(xiàn)了透明的零拷貝;
  • 容量可以按需增長(類似于 JDK 的 StringBuilder)
  • 在讀和寫這兩種模式之間切換不需要調(diào)用 ByteBuffer 的 flip()方法
  • 讀和寫使用了不同的索引
  • 支持方法的鏈?zhǔn)秸{(diào)用
  • 支持引用
  • 計數(shù)支持池化

其他類可用于管理 ByteBuf 實例的分配,以及執(zhí)行各種針對于數(shù)據(jù)容器本身和它所持有的數(shù)據(jù)的操作。

三、Netty 的數(shù)據(jù)容器

所有網(wǎng)絡(luò)通信最終都是基于底層的字節(jié)流傳輸,因此高效、方便、易用的數(shù)據(jù)接口是迷人的,而 Netty 的 ByteBuf 生而為滿足這些需求。

3.1 工作原理

ByteBuf 維護(hù)倆不同索引:一個用于讀取,一個用于寫入:

  • 從 ByteBuf 讀取時,其 readerIndex 將會被遞增已經(jīng)被讀取的字節(jié)數(shù)
  • 當(dāng)寫入 ByteBuf 時,writerIndex 也會被遞增
  • 一個讀索引和寫索引都設(shè)置為 0 的 16 字節(jié) ByteBuf


這些索引兩兩之間有什么關(guān)系呢?
若打算讀取字節(jié)直到 readerIndex == writerIndex,會發(fā)生啥?此時,將會到達(dá)“可讀取的”數(shù)據(jù)的末尾。類似試圖讀取超出數(shù)組末尾的數(shù)據(jù)一樣,試圖讀取超出該點(diǎn)的數(shù)據(jù)也會拋 IndexOutOfBoundsException

  • read、write 開頭的 ByteBuf 方法,會推進(jìn)對應(yīng)索引
  • set、get 開頭的操作則不會。后面的這些方法將在作為一個參數(shù)傳入的一個相對索引上執(zhí)行操作

可指定 ByteBuf 的最大容量。試圖移動寫索引(即 writerIndex)超過這個值將會觸
發(fā)一個異常。(默認(rèn)限制 Integer.MAX_VALUE。)

四、內(nèi)存池化

非池化的堆內(nèi)與堆外的 ByteBuf 示意圖

ByteBuf heapBuffer = UnpooledByteBufAllocator.DEFAULT.heapBuffer(10);
ByteBuf directBuffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(10);

注意要手動將GC 無法控制的非堆內(nèi)存的空間釋放:

池化的堆內(nèi)與堆外的 ByteBuf 示意圖

五、字節(jié)級操作

派生緩沖區(qū)

派生緩沖區(qū)為 ByteBuf 提供了以專門的方式來呈現(xiàn)其內(nèi)容的視圖。這類視圖通過以下方法創(chuàng)建:

  • Unpooled.unmodifiableBuffer(…)
  • order(ByteOrder)
  • readSlice(int)

這些方法都將返回一個新的 ByteBuf 實例,但都具有自己獨(dú)立的讀、寫和標(biāo)記索引。
其內(nèi)部存儲和 JDK 的 ByteBuffer 一樣,都是共享的。所以派生緩沖區(qū)的創(chuàng)建成本很低,但同時也表明若你修改了它的內(nèi)容,也會同時修改對應(yīng)源實例!

slice、slice(int, int)、retainedSlice、retainedSlice(int, int)

返回此緩沖區(qū)的可讀字節(jié)的一部分。
此方法與buf.slice(buf.readerIndex(), buf.readableBytes())相同。
該方法不會調(diào)用retain(),引用計數(shù)不會增加。
retainedSlice系列方法調(diào)用類似slice().retain(),但此方法可能返回產(chǎn)生較少垃圾的緩沖區(qū)實現(xiàn)。

duplicate、retainedDuplicate

返回一個共享該緩沖區(qū)整個區(qū)域的緩沖區(qū)。
此方法不會修改此緩沖區(qū)的readerIndex或writerIndex

讀取器和寫入器標(biāo)記將不會重復(fù)。
duplicate不會調(diào)用retain(),不會增加引用計數(shù),而retainedDuplicate會。

readSlice、readRetainedSlice

返回部分空間,彼此共享底層緩沖區(qū),會增加原緩沖區(qū)的readerIndex。

如果需要一個現(xiàn)有緩沖區(qū)的真實副本,請使用 copy()或者 copy(int, int),因為這個調(diào)用所返回的 ByteBuf 擁有獨(dú)立的數(shù)據(jù)副本。

六、引用與釋放

ByteBuf 在使用完畢后一定要記得釋放,否則會造成內(nèi)存泄露。

引用計數(shù)

通過在某個對象所持有的資源不再被其他對象引用時釋放該對象所持有的資源來優(yōu)化內(nèi)存使用和性能的技術(shù)。
Netty 在4.x為 ByteBuf 和 ByteBufHolder 帶來了引用計數(shù)技術(shù),都實現(xiàn)了:

ReferenceCounted接口

需要顯式釋放的引用計數(shù)對象。

當(dāng)一個新的ReferenceCounted被實例化時,以1 作為初始值。

retain()

增加引用計數(shù),將引用計數(shù)加1。只要引用計數(shù)>0,就能保證對象不會被釋放。

release()

減少引用計數(shù),將引用計數(shù)減1。若引用計數(shù)減少到0 ,對象將被顯式釋放,并且訪問釋放的對象通常會導(dǎo)致訪問沖突。

若實現(xiàn)ReferenceCounted的對象是其他實現(xiàn)ReferenceCounted的對象的容器,則當(dāng)容器的引用計數(shù)變?yōu)?0 時,所包含的對象也將通過release()被釋放。

引用計數(shù)對于池化實現(xiàn)(如 PooledByteBufAllocator)很重要,它降低了內(nèi)存分配的開銷。

Channel channel = ...;
// 從 Channel 獲取 ByteBufAllocator
ByteBufAllocator allocator = channel.alloc();
...
// 從 ByteBufAllocator 分配一個 ByteBuf
ByteBuf buffer = allocator.directBuffer();
// 檢查引用計數(shù)是否為預(yù)期的 1
assert buffer.refCnt() == 1;


ByteBuf buffer = ...;
// 減少該對象的活動引用。當(dāng)減少到 0 時,該對象被釋放,該方法返回 true
boolean released = buffer.release();

試圖訪問一個已經(jīng)被釋放的引用計數(shù)的對象,將會拋IllegalReferenceCountException

一個特定的(ReferenceCounted 的實現(xiàn))類,可以用它自己的獨(dú)特方式來定義它的引用計數(shù)規(guī)則。例如可以設(shè)想一個類,其 release()方法的實現(xiàn)總是將引用計數(shù)設(shè)為
零,而不用關(guān)心它的當(dāng)前值,從而一次性使所有的活動引用都失效。

誰負(fù)責(zé)釋放

一般由最后訪問(引用計數(shù))對象的那一方來負(fù)責(zé)將它釋放。

到此這篇關(guān)于又又叕出BUG啦!理智分析Java NIO的ByteBuffer到底有多難用的文章就介紹到這了,更多相關(guān)Java NIO的ByteBuffer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談JVM垃圾回收之哪些對象可以被回收

    淺談JVM垃圾回收之哪些對象可以被回收

    這篇文章主要介紹了JVM垃圾回收之哪些對象可以被回收,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java并發(fā)編程-volatile可見性詳解

    Java并發(fā)編程-volatile可見性詳解

    這篇文章主要介紹了Java并發(fā)編程-volatile可見性詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 圖解Java排序算法之堆排序

    圖解Java排序算法之堆排序

    這篇文章主要為大家詳細(xì)介紹了Java經(jīng)典排序算法之堆排序,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java利用redis zset實現(xiàn)延時任務(wù)詳解

    Java利用redis zset實現(xiàn)延時任務(wù)詳解

    zset作為redis的有序集合數(shù)據(jù)結(jié)構(gòu)存在,排序的依據(jù)就是score。本文就將利用zset score這個排序的這個特性,來實現(xiàn)延時任務(wù),感興趣的可以了解一下
    2022-08-08
  • Java中的ArrayList.trimToSize()方法詳解

    Java中的ArrayList.trimToSize()方法詳解

    這篇文章主要介紹了Java中的ArrayList.trimToSize()方法詳解,前幾天看了Java?ArrayList,沒有明白trimToSize()這個方法是什么意思,所以看了一下源碼并且debug一下自己的一個例子,明白了其中的含義,需要的朋友可以參考下
    2023-11-11
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(48)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(48)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-08-08
  • jenkins配置詳細(xì)指南(附j(luò)dk多個版本配置)

    jenkins配置詳細(xì)指南(附j(luò)dk多個版本配置)

    Jenkins是一款CICD(持續(xù)集成與持續(xù)交付)工具,Jenkins可以幫你在寫完代碼后,一鍵完成開發(fā)過程中的一系列自動化部署的工作,這篇文章主要給大家介紹了關(guān)于jenkins配置的相關(guān)資料,文中還附j(luò)dk多個版本配置指南,需要的朋友可以參考下
    2024-02-02
  • java實現(xiàn)切割wav音頻文件的方法詳解【附外部jar包下載】

    java實現(xiàn)切割wav音頻文件的方法詳解【附外部jar包下載】

    這篇文章主要介紹了java實現(xiàn)切割wav音頻文件的方法,結(jié)合實例形式詳細(xì)分析了java切割wav音頻文件的相關(guān)原理、操作技巧與注意事項,并附帶外部jar包供讀者下載,需要的朋友可以參考下
    2019-05-05
  • 實現(xiàn)分布式WebSocket集群的方法

    實現(xiàn)分布式WebSocket集群的方法

    本文總結(jié)出了幾個實現(xiàn)分布式WebSocket集群的辦法,從zuul到spring cloud gateway的不同嘗試,總結(jié)出了這篇文章,希望能幫助到某些人,并且能一起分享這方面的想法與研究
    2022-03-03
  • java Collection 之Set使用說明

    java Collection 之Set使用說明

    本篇文章小編為大家介紹,java Collection 之Set使用說明。需要的朋友參考下
    2013-04-04

最新評論