您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)如何在.NET Core中使用Object Pool,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
前言
復(fù)用,是一個(gè)重要的話題,也是我們?nèi)粘i_(kāi)發(fā)中經(jīng)常遇到的,不可避免的問(wèn)題。
舉個(gè)最為簡(jiǎn)單,大家最為熟悉的例子,數(shù)據(jù)庫(kù)連接池,就是復(fù)用數(shù)據(jù)庫(kù)連接。
那么復(fù)用的意義在那里呢?
簡(jiǎn)單來(lái)說(shuō)就是減少不必要的資源損耗。
除了數(shù)據(jù)庫(kù)連接,可能在不同的情景或需求下,還會(huì)有很多其他對(duì)象需要進(jìn)行復(fù)用,這個(gè)時(shí)候就會(huì)有所謂的 Object Pool(對(duì)象池)。
小伙伴們應(yīng)該也自己實(shí)現(xiàn)過(guò)類似的功能,或用ConcurrentBag,或用ConcurrentQueue,或用其他方案。
這也里分享一個(gè)在微軟文檔中的實(shí)現(xiàn)
How to: Create an Object Pool by Using a ConcurrentBag
當(dāng)然,在.NET Core中,微軟已經(jīng)幫我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的Object Pool。
我們只需要添加Microsoft.Extensions.ObjectPool的引用即可使用了。
Microsoft.Extensions.ObjectPool
Microsoft.Extensions.ObjectPool可以說(shuō)是.NET Core的一個(gè)基礎(chǔ)類庫(kù)。
它位于aspnet的Common項(xiàng)目中,類型其他基礎(chǔ)模塊都有使用相關(guān)的功能,也好比Routing項(xiàng)目。
下面就簡(jiǎn)單看看它的用法。
在開(kāi)始之前,我們先定義一個(gè)可以復(fù)用的object
public class Demo { public int Id { get; set; } public string Name { get; set; } public DateTime CreateTimte { get; set; } }
用法1
var defalutPolicy = new DefaultPooledObjectPolicy<Demo>(); //最大可保留對(duì)象數(shù)量 = Environment.ProcessorCount * 2 var defaultPool = new DefaultObjectPool<Demo>(defalutPolicy); for (int i = 0; i < PoolSize; i++) { item1 = defaultPool.Get(); Console.WriteLine($"#{i+1}-{item1.Id}-{item1.Name}-{item1.CreateTimte}"); }
在創(chuàng)建pool之前,我們要先定義一個(gè)Policy。這里直接用自帶的DefaultPooledObjectPolicy來(lái)構(gòu)造。
對(duì)象池會(huì)有一個(gè)維護(hù)的最大數(shù)量,線程數(shù)。
通過(guò)pool對(duì)象的Get方法,從對(duì)象池中取出一個(gè)對(duì)象。
上面代碼運(yùn)行結(jié)果
#1-0--01/01/0001 00:00:00
#2-0--01/01/0001 00:00:00
#3-0--01/01/0001 00:00:00
#4-0--01/01/0001 00:00:00
#5-0--01/01/0001 00:00:00
#6-0--01/01/0001 00:00:00
#7-0--01/01/0001 00:00:00
#8-0--01/01/0001 00:00:00
這個(gè)結(jié)果說(shuō)明,Object Pool 中的對(duì)象都是直接new出來(lái)的,并沒(méi)有對(duì)一些屬性進(jìn)行貶值操作,這個(gè)時(shí)候往往沒(méi)有太多實(shí)際意義。
因?yàn)?code>DefaultPooledObjectPolicy本來(lái)就是直接new了一個(gè)對(duì)象出來(lái),很多時(shí)候,這并不是我們所期望的!
要想符合我們實(shí)際的使用,就要自己定義一個(gè)Policy!
下面來(lái)看看用法2
用法2
先定義一個(gè)Policy,實(shí)現(xiàn) IPooledObjectPolicy 這個(gè)接口。T很自然就是我們的Demo類了。
public class DemoPooledObjectPolicy : IPooledObjectPolicy<Demo> { public Demo Create() { return new Demo { Id = 1, Name = "catcher", CreateTimte = DateTime.Now }; } public bool Return(Demo obj) { return true; } }
這里要實(shí)現(xiàn)Create和Return兩個(gè)方法。
見(jiàn)名知義,Create方法就是用來(lái)創(chuàng)建Demo對(duì)象的,Return方法就是將Demo對(duì)象扔回Object Pool的(有借有還)。
然后是用DemoPooledObjectPolicy去替換DefaultPooledObjectPolicy。
var demoPolicy = new DemoPooledObjectPolicy(); var defaultPoolWithDemoPolicy = new DefaultObjectPool<Demo>(demoPolicy,1); //借 item1 = defaultPoolWithDemoPolicy.Get(); //還 defaultPoolWithDemoPolicy.Return(item1); //借,但是不還 item2 = defaultPoolWithDemoPolicy.Get(); Console.WriteLine($"{item1.Id}-{item1.Name}-{item1.CreateTimte}"); Console.WriteLine($"{item2.Id}-{item2.Name}-{item2.CreateTimte}"); Console.WriteLine(item1 == item2); //創(chuàng)建一個(gè)新的 item3 = defaultPoolWithDemoPolicy.Get(); Console.WriteLine($"{item3.Id}-{item3.Name}-{item3.CreateTimte}"); Console.WriteLine(item3 == item1);
這里定義了對(duì)象池只保留一個(gè)對(duì)象。
由于從object pool中取出來(lái)之后,有一步還回去的操作,所以item1和item2應(yīng)當(dāng)是同一個(gè)對(duì)象。
從object pool中拿出了item2之后,它并沒(méi)有還回去,所以object pool會(huì)基于我們定義的Policy去創(chuàng)建一個(gè)新的對(duì)象出來(lái)。
下面是用法2的輸出結(jié)果:
1-catcher-09/17/2018 22:32:38
1-catcher-09/17/2018 22:32:38
True
1-catcher-09/17/2018 22:32:38
False
可以看到item1,item2和item3的各個(gè)屬性是一樣的,并且item1和item2確實(shí)是同一個(gè)對(duì)象。item3和item1并不是同一個(gè)。
用法3
除了DefaultObjectPool外,還有DefaultObjectPoolProvider也可以創(chuàng)建一個(gè)Object Pool。
創(chuàng)建一個(gè)Object Pool,一定是離不開(kāi)Policy的,所以這里還是用了我們自己定義的DemoPooledObjectPolicy。
var defaultProvider = new DefaultObjectPoolProvider(); var policy = new DemoPooledObjectPolicy(); //default maximumRetained is Environment.ProcessorCount * 2 ObjectPool<Demo> pool = defaultProvider.Create(policy); item1 = pool.Get(); pool.Return(item1); item2 = pool.Get(); Console.WriteLine($"{item1.Id}-{item1.Name}-{item1.CreateTimte}"); Console.WriteLine($"{item2.Id}-{item2.Name}-{item2.CreateTimte}"); Console.WriteLine(item1 == item2); item3 = pool.Get(); Console.WriteLine($"{item3.Id}-{item3.Name}-{item3.CreateTimte}"); Console.WriteLine(item3 == item2);
用Provider創(chuàng)建Object Pool時(shí),不能指定保留的最大對(duì)象數(shù)量,只能用的是默認(rèn)的Environment.ProcessorCount * 2。
后面的使用,和用法2是一樣的。
可以看到item1和item2是同一個(gè)對(duì)象。從Object Pool中取對(duì)象的時(shí)候,會(huì)取第一個(gè),所以還回去后,再取的話,還是會(huì)取到原來(lái)的第一個(gè)。
item3那里是直接從Object Pool中取出來(lái)的,沒(méi)有再次創(chuàng)建,因?yàn)檫@里的Object Pool維護(hù)著多個(gè)對(duì)象,而不是用法2中的只有一個(gè),所以它是直接從Pool中拿的。
下面是輸出結(jié)果
1-catcher-09/17/2018 22:38:34
1-catcher-09/17/2018 22:38:34
True
1-catcher-09/17/2018 22:38:34
False
和用法2,本質(zhì)是一樣的。
用法4
好像上面的用法,都不那么像我們正常使用的。我們還是需要依賴注入的。
那么我們最后就來(lái)看看怎么結(jié)合依賴注入吧。當(dāng)然這里的本質(zhì)還是離不開(kāi)Policy和Provider這兩個(gè)東西。
IServiceCollection services = new ServiceCollection(); services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>(); services.AddSingleton(s => { var provider = s.GetRequiredService<ObjectPoolProvider>(); return provider.Create(new DemoPooledObjectPolicy()); }); ServiceProvider serviceProvider = services.BuildServiceProvider(); var pool = serviceProvider.GetService<ObjectPool<Demo>>(); item1 = pool.Get(); pool.Return(item1); item2 = pool.Get(); Console.WriteLine($"{item1.Id}-{item1.Name}-{item1.CreateTimte}"); Console.WriteLine($"{item2.Id}-{item2.Name}-{item2.CreateTimte}"); Console.WriteLine(item1 == item2); item3 = pool.Get(); Console.WriteLine($"{item3.Id}-{item3.Name}-{item3.CreateTimte}"); Console.WriteLine(item3 == item2);
我們首先需要完成對(duì)Provider的注冊(cè),然后直接拿它的實(shí)例去創(chuàng)建一個(gè)Object Pool即可。
如果想在其他地方用,通過(guò)構(gòu)造函數(shù)注入即可。
這里的結(jié)果也是和前面一樣的,沒(méi)什么好多說(shuō)的。
總結(jié)
在這幾種用法中,我們最常用的應(yīng)該是用法4。
但是無(wú)論那種用法,我們都需要了解,Object Pool離不開(kāi)Pool,Policy和Provider這三個(gè)家伙。
有了這三個(gè),或許我們就可以為所欲為了。
當(dāng)然,它還提供了幾個(gè)特殊的東西,有興趣的可以去看看。
?LeakTrackingObjectPool
?StringBuilderPooledObjectPolicy
最后用一個(gè)腦圖結(jié)束本文。
上述就是小編為大家分享的如何在.NET Core中使用Object Pool了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。