ArrayPool是一個抽象類,框架沒有暴露具體實現類,只是通過ArrayPool類的靜態方法創建或者獲取一個ArrayPool類的實例,並且框架內部所有通過抽象類暴露接口的實現也都是線程安全的
ArrayPool類的作用相當於數組所有權轉移的中間代理者,可以從池中租用一塊大小不小於指定長度的數組,如果當前池中沒有可用數組實例會自動創建一個,當使用完畢后可以將數組返還池中,池中有一個閾值,會自動放棄多余數組的引用,這樣數組就會被GC回收(若沒有其他引用存在),所以根據實現租用了不返回並不會造成致命問題,但是將池中租用的數組實例返回池中后繼續使用或者返回了大於一次則是致命錯誤
可以通過兩種方式獲取ArrayPool的實例,一個是通過靜態屬性Shared獲取一個公共實例,因為ArrayPool是泛型類型,所以每一個通過泛型參數具體化的類都有一個獨立的公共實例
ArrayPool<byte> byteArrayPool = ArrayPool<byte>.Shared; ArrayPool<char> charArrayPool = ArrayPool<char>.Shared; Console.WriteLine(object.ReferenceEquals(byteArrayPool, charArrayPool));
另一個方法是通過靜態方法Create創建一個新的實例,Create方法有兩個參數的重載
public static ArrayPool<T> Create (int maxArrayLength, int maxArraysPerBucket);
通過這個重載我們可以自定義池的容量,池中會將長度相似的數組實例放到一個“桶”中,每個“桶”中的數組實例的個數不超過maxArraysPerBucket,並且池中數組實例的最大長度不超過maxArrayLength,(個人猜測這也限制了“桶”的數量)
ArrayPool<byte> byteArrayPool = ArrayPool<byte>.Create(81920, 10);
有一個區別是這兩個方法獲得的池的具體內部實現類並不一樣
//輸出 System.Buffers.TlsOverPerCoreLockedStacksArrayPool`1[System.Byte] Console.WriteLine(ArrayPool<byte>.Shared.GetType()); //輸出 System.Buffers.ConfigurableArrayPool`1[System.Byte] Console.WriteLine(ArrayPool<byte>.Create(81920, 10).GetType());
租用數組使用實例方法Rent(int minimumLength),注意此方法返回的內存長度保證不會小於minimumLength,但可能大於minimumLength,並且根據返還池中時的選項,數組中可能包含上一次租用時所使用的數據
返還數組使用實例方法Return(T[] array, bool clearArray = false),第一個參數就是將要返還的數組,返還數組代表所有權的轉移。第二個參數默認值為false,如果為true的話,會將數組的內容清0,若數組是引用類型的數組並且clearArray為false的話那么數組中所引用的實例可能不會被GC回收(除非池中到達閾值沒有保留數組的引用)
string[] strs = ArrayPool<string>.Shared.Rent(1024); //使用數組 //... ArrayPool<string>.Shared.Return(strs, true);