第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Netty 教程 Netty 教程 Netty ByteBuf幾種類型

Netty ByteBuf 幾種類型

1. 前言

上一節(jié),我們主要學(xué)習(xí)了 ByteBuf 的核心 API,相信大家都能掌握,本節(jié)主要介紹 ByteBuf 的幾種分類。

2. 創(chuàng)建一個 ByteBuf

常見創(chuàng)建 ByteBuf 主要有兩種方式,分別如下所示:

方式一:

ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(10);

方式二:

ByteBuf byteBuf = Unpooled.buffer(10);

思考:那么這兩種方式有什么關(guān)聯(lián)呢?

Unpooled.buffer 源碼,以下代碼是經(jīng)過整理,只保留了核心代碼。

public final class Unpooled {
    private static final ByteBufAllocator ALLOC;
    
    static {
        ALLOC = UnpooledByteBufAllocator.DEFAULT;
    }
    
    public static ByteBuf buffer(int initialCapacity) {
        return ALLOC.heapBuffer(initialCapacity);
    }
    
    public static ByteBuf directBuffer() {
        return ALLOC.directBuffer();
    }
}

通過源碼,我們可以知道,其實 Unpooled 工具類也是調(diào)用 ByteBufAllocator 去創(chuàng)建 ByteBuf 的。從字面上我們能夠大概猜到它針對的是非池化的 ByteBuf 進行創(chuàng)建的。

3. ByteBuf 分類

ByteBuf 是一個字節(jié)容器,底層是根據(jù)容量值來申請一塊內(nèi)存區(qū)域來存儲字節(jié)數(shù)組的。既然涉及到內(nèi)存,那么會分為直接內(nèi)存和 JVM 內(nèi)存,這個和 NIO 的直接緩沖器和非直接緩沖器是一樣的道理。直接內(nèi)存,速度很快,垃圾回收是不受 JVM 控制,容易造成內(nèi)存爆滿。

ByteBuf 主要分為三種類型

  1. Pooled 和 Unpooled,池化和非池化;
  2. Heap 和 Direct,堆內(nèi)存和直接內(nèi)存;
  3. Safe 和 Unsafe,安全和非安全。

池化和非池化: 池化就是用完就放回池子里面,比如我們所熟悉的數(shù)據(jù)庫連接池。非池化就是每次使用都重新創(chuàng)建,使用完成則立馬銷毀。從性能的角度來說,池化會比非池化相對高,因為可以重復(fù)利用,避免每次都重新創(chuàng)建。

堆內(nèi)存和直接內(nèi)存: 堆內(nèi)存是 JVM 內(nèi)部開辟的一塊內(nèi)存空間,它的生命周期受到 JVM 來管理,不容易造成內(nèi)存溢出的情況。直接內(nèi)存則是直接受操作系統(tǒng)管理了,如果數(shù)據(jù)量很大的情況,容易造成內(nèi)存溢出情況。

安全和非安全: 主要是 Java 操作底層操作數(shù)據(jù)的一種安全和非安全的方式。

圖片描述

根據(jù)不同類型進行組合,得到常見 ByteBuf 的實現(xiàn)類

  1. 池化 + 堆內(nèi)存,PooledHeapByteBuf;
  2. 池化 + 直接內(nèi)存,PooledDirectByteBuf;
  3. 池化 + 堆內(nèi)存 + 不安全,PooledUnsafeHeapByteBuf;
  4. 池化 + 直接內(nèi)存 + 不安全,PooledUnsafeDirectByteBuf;
  5. 非池化 + 堆內(nèi)存,UnpooledHeapByteBuf;
  6. 非池化 + 直接內(nèi)存,UnpooledDirectByteBuf;
  7. 非池化 + 堆內(nèi)存 + 不安全,UnpooledUnsafeHeapByteBuf;
  8. 非池化 + 直接內(nèi)存 + 不安全,UnpooledUnsafeDirectByteBuf。

4. ByteBufAllocator 的使用

由于 ByteBuf 的組合種類非常的多,如果讓用戶手工去創(chuàng)建的化,會非常的麻煩,并且對每種類型不熟悉,很容易出現(xiàn)性能問題。這點跟 Java 線程池有點類似,線程池的種類分好幾種,但是通常都是通過 Executors 工具類來進行線程池的創(chuàng)建。

其中,ByteBufAllocator 又主要分為兩種,分別是 UnpooledByteBufAllocatorPooledByteBufAllocator。其實,一般情況下我們不需要直接使用具體的分配器,而是使用它默認的即可。

4.1 默認分配 - 池化 & 非池化

實例:

ByteBufAllocator byteBufAllocator = ByteBufAllocator.DEFAULT;

源碼:

public interface ByteBufAllocator {
    ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;
}

源碼:以下源碼是經(jīng)過處理,只保留核心部分。

public final class ByteBufUtil {
    static final ByteBufAllocator DEFAULT_ALLOCATOR;
    static {
        //1.分配類型
        String allocType = SystemPropertyUtil.get("io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");
        
        //2.根據(jù)類型,創(chuàng)建不同的分配器
        Object alloc;
        if ("unpooled".equals(allocType)) {
            alloc = UnpooledByteBufAllocator.DEFAULT;
            
        } else if ("pooled".equals(allocType)) {
            alloc = PooledByteBufAllocator.DEFAULT;
            
        } else {
            alloc = PooledByteBufAllocator.DEFAULT;
        }

        DEFAULT_ALLOCATOR = (ByteBufAllocator)alloc;
    }
}

根據(jù)以上的源碼,我們可以知道,使用 ByteBufAlloctor 來創(chuàng)建 ByteBuf 時,會判斷使用池化還是非池化的分配器。

4.2 默認分配 - 堆內(nèi)存 & 直接內(nèi)存

實例:

ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(10);

源碼:以下源碼是經(jīng)過處理,只保留核心部分。

public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
    private final boolean directByDefault;
    
    //構(gòu)造函數(shù)
    protected AbstractByteBufAllocator(boolean preferDirect) {
        this.directByDefault = preferDirect && PlatformDependent.hasUnsafe();
    }
    
    public ByteBuf buffer(int initialCapacity) {
        return this.directByDefault ? this.directBuffer(initialCapacity) : this.heapBuffer(initialCapacity);
    }
}

通過 directByDefault 來判斷是否選擇創(chuàng)建堆內(nèi)存還是直接內(nèi)存的 ByteBuf,而 directByDefault 是在構(gòu)造函數(shù)里面進行傳值的,那么它是一個抽象類,因此肯定是從其子類的構(gòu)造函數(shù)傳值進來。

繼續(xù)查看源碼:

public class PooledByteBufAllocator extends AbstractByteBufAllocator {
    public PooledByteBufAllocator() {
        //傳遞的是false
        this(false);
    }
}

public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {
    public UnpooledByteBufAllocator(boolean preferDirect) {
        this(preferDirect, false);
    }

    public UnpooledByteBufAllocator(boolean preferDirect, boolean disableLeakDetector) {
        //傳遞值給父類的構(gòu)造函數(shù)
        super(preferDirect);
        this.disableLeakDetector = disableLeakDetector;
    }
}

總結(jié),ByteBufAllocator 的核心兩個步驟分別如下:

  1. 確定是使用哪個分配器,池化還是非池化?UnpooledByteBufAllocatorPooledByteBufAllocator;
  2. 再確定是堆內(nèi)存還是直接內(nèi)存,主要是在 UnpooledByteBufAllocatorPooledByteBufAllocator 的構(gòu)造函數(shù)里面?zhèn)髦荡_定。

4.3 核心方法

方式 描述
buffer(); 創(chuàng)建 ByteBuf(堆內(nèi)存還是直接內(nèi)存?),默認容量值
buffer(int var1); 創(chuàng)建 ByteBuf(堆內(nèi)存還是直接內(nèi)存?),手工指定容量值
buffer(int var1, int var2); 創(chuàng)建 ByteBuf(堆內(nèi)存還是直接內(nèi)存?),手工指定容量值和最大容量值
heapBuffer(); 創(chuàng)建一個堆內(nèi)存的 ByteBuf,默認容量值
heapBuffer(int var1); 創(chuàng)建一個堆內(nèi)存的 ByteBuf,手工指定容量值
heapBuffer(int var1, int var2); 創(chuàng)建一個堆內(nèi)存的 ByteBuf,手工指定容量值和最大容量值
directBuffer(); 創(chuàng)建一個直接內(nèi)存的 ByteBuf,默認容量值
directBuffer(int var1); 創(chuàng)建一個直接內(nèi)存的 ByteBuf,手工指定容量值
directBuffer(int var1, int var2); 創(chuàng)建一個直接內(nèi)存的 ByteBuf,手工指定容量值和最大容量值

一般推薦使用 buffer ()、buffer(int var1)、buffer(int var1,int var2),因為 Netty 底層回去幫選擇創(chuàng)建最優(yōu)的 ByteBuf。

5. Unpooled 的使用

Unpooled 主要是使用了非池化技術(shù),可以創(chuàng)建堆內(nèi)存和直接內(nèi)存的 ByteBuf。

核心 API 如下所示:

方法 描述
ByteBuf buffer() 創(chuàng)建非池化 + 堆內(nèi)存的 ByteBuf,默認容量大小
ByteBuf buffer(int initialCapacity) 創(chuàng)建非池化 + 堆內(nèi)存的 ByteBuf,并且可以指定容量大小
ByteBuf directBuffer() 創(chuàng)建非池化 + 直接內(nèi)存的 ByteBuf,默認容量大小
directBuffer(int initialCapacity) 創(chuàng)建非池化 + 直接內(nèi)存的 ByteBuf,并且可以指定容量大小
ByteBuf copiedBuffer(byte[] array) 創(chuàng)建非池化 + 堆內(nèi)存的 ByteBuf,并且初始化字節(jié)數(shù)組
ByteBuf copiedBuffer(byte[] array, int offset, int length) 創(chuàng)建非池化 + 堆內(nèi)存的 ByteBuf,并且把字節(jié)數(shù)組的部分內(nèi)容初始化到 ByteBuf
ByteBuf copiedBuffer(ByteBuf buffer) 創(chuàng)建非池化 + 堆內(nèi)存的 ByteBuf,并且把參數(shù)的 ByteBuf 寫入到新創(chuàng)建的 ByteBuf 里

以上的方法是平時我們使用 Unpooled 時使用最多的,難度不大,只需要分清每個方法的作用是什么即可,可以根據(jù)自己需求選擇合適的 ByteBuf 類型。

6. 小結(jié)

本節(jié)主要介紹了 ByteBuf 的幾種核心類型以及創(chuàng)建 ByteBuf 的幾種方式

  1. 掌握 ByteBuf 的三種類型,分別是池化與非池化、堆內(nèi)存與直接內(nèi)存、安全與不安全,以及它們之間的含義;
  2. ByteBufAllocator 分配器,它是如何去創(chuàng)建 ByteBuf 的,幾種模式;
  3. Unpooled,Netty 提供的非池化工具類。