您好,登錄后才能下訂單哦!
這篇文章主要講解了“.NET Core中對象池Object Pool的使用方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“.NET Core中對象池Object Pool的使用方法是什么”吧!
對象池簡單來說就是一種為對象提供可復用能力的軟件設計思路。我們常說有借有還,再借不難,而對象池就是通過借和還這樣兩個動作來保證對象可以被重復使用,從而節省頻繁創建對象的性能開銷。對象池最常用的場景是游戲設計,因為在游戲中大量存在著可復用的對象,源源不斷的子彈出現并不是循環再生的。在數據庫中存在著被稱為連接池的東西,每當出現數據庫無法連接的情況時,經驗豐富的開發人員往往會先檢查連接池是否滿了,這其實就是對象池模式在特定領域的具體實現。因此對象池本質上就是負責一組對象創建和銷毀的容器。 對象池最大的優勢是可以自主地管理池子內的每個對象,決定它們是需要被回收還是可以重復使用。我們都知道創建一個新對象需要消耗一定的系統資源,一旦這些對象可以重復地使用就可以節省系統資源開銷,這對提高系統性能會非常有幫助。下面的代碼實微軟官方文檔實現的一個簡單的對象池:
public class ObjectPool<T> : IObjectPool<T> { private Func<T> _instanceFactory; private ConcurrentBag<T> _instanceItems; public ObjectPool(Func<T> instanceFactory) { _instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory)); _instanceItems = new ConcurrentBag<T>(); } public T Get() { T item; if (_instanceItems.TryTake(out item)) return item; return _instanceFactory(); } public void Return(T item) { _instanceItems.Add(item); } }
在.NET Core
中微軟已經為我們提供了對象池的實現,即Microsoft.Extensions.ObjectPool
。它主要提供了三個核心的組件,分別是ObjectPool
、ObjectPoolProvider
和IPooledObjectPolicy
。ObjectPool
是一個抽象類,對外提供了Get和Return兩個方法,這就是所謂的有借有還。ObjectPoolProvider
同樣是一個抽象類,它的職責就是創建ObjectPool,它提供了兩個Create方法,兩者的區別是無參數版本本質上使用的是DefaultPooledObjectPolicy
。它和DefaultObjectPool
、DefaultObjectPoolProvider都是微軟提供的默認實現,IPooledObjectPolicy可以為不同的對象池定義不同的策略,來決定對象如何借、是否可以還。DefaultObjectPool內部使用ObjectWrapper[]來管理對象,ObjectWrapper[]的大小等于 maximumRetained-1,默認情況下maximumRetained等于Environment.ProcessorCount * 2
,這里主要用到了Interlocked.CompareExchange()
方法,
具體代碼如下:
public override T Get() { var item = _firstItem; if (item == null || Interlocked.CompareExchange(ref _firstItem, null, item) != item) { var items = _items; for (var i = 0; i < items.Length; i++) { item = items[i].Element; if (item != null && Interlocked.CompareExchange(ref items[i].Element, null, item) == item) { return item; } } item = Create(); } return item; } // Non-inline to improve its code quality as uncommon path [MethodImpl(MethodImplOptions.NoInlining)] private T Create() => _fastPolicy?.Create() ?? _policy.Create(); public override void Return(T obj) { if (_isDefaultPolicy || (_fastPolicy?.Return(obj) ?? _policy.Return(obj))) { if (_firstItem != null || Interlocked.CompareExchange(ref _firstItem, obj, null) != null) { var items = _items; for (var i = 0; i < items.Length && Interlocked.CompareExchange(ref items[i].Element, obj, null) != null; ++i) { } } } }
這里用到Interlocked.CompareExchange()
方法,Get()方法將items[i].Element
和null
進行交換,將指定元素設為 null 并返回原始值。Return()方法將items[i].Element
和obj交換后的值不為 null,表示指定元素已經歸還,這個方法只有在第一個參數和第三個參數相等時才會發生交換。
說了這么多,我們來看一下對象池具體的用法:
var service = new ServiceCollection(); //使用DefaultObjectPoolProvider service.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>(); //使用默認策略 service.AddSingleton<ObjectPool<Foo>>(serviceProvider => { var objectPoolProvider = serviceProvider.GetRequiredService<ObjectPoolProvider>(); return objectPoolProvider.Create<Foo>(); }); //使用自定義策略 service.AddSingleton<ObjectPool<Foo>>(serviceProvider => { var objectPoolProvider = serviceProvider.GetRequiredService<ObjectPoolProvider>(); return objectPoolProvider.Create(new FooObjectPoolPolicy()); }); var serviceProvider = _service.BuildServiceProvider(); var objectPool = _serviceProvider.GetService<ObjectPool<Foo>>(); //有借有還,兩次是同一個對象 var item1 = objectPool.Get(); objectPool.Return(item1); var item2 = objectPool.Get(); Assert.AreEqual(item1, item2);//true //有借無還,兩次是不同的對象 var item3 = objectPool.Get(); var item4 = objectPool.Get(); Assert.AreEqual(item3, item4);//false
上面的代碼中Foo和FooObjectPoolPolicy是兩個工具類:
public class Foo { public string Id { get; set; } public DateTime? CreatedAt { get; set; } public string CreatedBy { get; set; } } public class FooObjectPoolPolicy : IPooledObjectPolicy<Foo> { public Foo Create() { return new Foo() { Id = Guid.NewGuid().ToString("N"), CreatedAt = DateTime.Now, CreatedBy = "zs" }; } public bool Return(Foo obj) { return true; } }
TIP:當你需要控制對象池內的對象如何被創建的時候,你可以考慮實現自定義的IPooledObjectPolicy<T>
,反之DefaultPooledObjectPolicy<T>
實現完全可以滿足你的使用。
感謝各位的閱讀,以上就是“.NET Core中對象池Object Pool的使用方法是什么”的內容了,經過本文的學習后,相信大家對.NET Core中對象池Object Pool的使用方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。