手机版

中对象池各种用途的详细说明 净核心

时间:2021-08-29 来源:互联网 编辑:宝哥软件园 浏览:

前言

复用是一个重要的话题,也是我们在日常开发中经常遇到的不可避免的问题。

最简单也是最熟悉的例子,数据库连接池,就是重用数据库连接。

那么复用的意义是什么呢?

简单来说,就是减少不必要的资源损失。

除了数据库连接之外,可能还有很多其他的对象需要在不同的场景或者需求下重用,这时候就会出现所谓的对象池。

朋友们应该自己实现类似的功能,或者使用ConcurrentBag、ConcurrentQueue或其他方案。

这也共享了微软文档中的一个实现

如何使用并发包创建对象池

当然,在。微软帮助我们实现了一个简单的对象池。

我们只需要添加对微软的引用。扩展。ObjectPool。

微软。扩展。对象池

微软。extensions.objectpool可以说是。NET核心。

它位于aspnet的Common项目中,该类型的其他基本模块都有相关的功能,就像Routing项目一样。

让我们简单了解一下它的用法。

在开始之前,我们首先定义一个可重用的对象

公共类Demo { public int Id { get设置;}公共字符串名称{ get设置;}公共DateTime CreateTimte { get设置;}}用法1

var defaultpolicy=new defaultpooledobjectpolicy demo();//可以保留的最大对象数=环境。processor count * 2var default pool=new default objectpool demo(default policy);for(int I=0;i PoolSizei ){ item1=defaultPool。get();控制台。WriteLine($'#{i 1}-{item1。Id}-{item1。名称}-{item1。create Timote } ');}在创建池之前,我们必须定义一个策略。这里,它直接用自己的DefaultPooledObjectPolicy构造。

对象池将有最大数量的线程需要维护。

通过池对象的Get方法从对象池中获取对象。

运行上述代码的结果

#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

这个结果表明,对象池中的对象都是直接新的,有些属性没有贬值,所以此时没有太大的实际意义。

因为DefaultPooledObjectPolicy最初直接创建了一个对象,在很多情况下,这并不是我们所期望的!

如果我们想满足我们的实际使用,我们必须自己定义一个策略!

让我们来看看用法2

用法2

首先,定义一个策略并实现接口IPooledObjectPolicy。t自然是我们的Demo类。

公共类demopoledobjectpolicy : ipooledobjectpolicy Demo { public Demo Create(){返回新的Demo { Id=1,Name='catcher ',CreateTimte=DateTime。现在};}公共bool Return(Demo obj){ Return true;}}这里要实现两个方法,Create和Return。

看到名称和含义,Create方法用于创建Demo对象,Return方法用于将Demo对象抛出回对象池。

然后将DefaultPooledObjectPolicy替换为DemoPooledObjectPolicy。

var DemoPoLicy=new DemopooledObjectPoLicy();var defaultpoolwitempolicy=new DefaultObjectPoolDemo(demo policy,1);//借用item 1=defaultpoolwitepemopolicy . get();//也是defaultpoolwithdemopolicy。退货(项目1);//借用,但不返回Item2=DefaultPoolwithDemoPolicy。get();控制台。WriteLine($'{item1。Id}-{item1。名称}-{item1。create Timote } ');控制台。WriteLine($'{item2。Id}-{item2。名称}-{item2。create Timote } ');控制台。write line(item 1==item 2);//新建一个item 3=defaultpoolwitepemopolicy . get();控制台。WriteLine($'{item3。Id}-{item3。名称}-{item3。create Timote } ');控制台。write line(item 3==item 1);这里定义了对象池只保留一个对象。

Item1和item2应该是同一个对象,因为从对象池中取出后有一个返回的步骤。

从对象池中取出项目2后,它不会被返回,因此对象池将根据我们定义的策略创建一个新的对象。

以下是用法2的输出:

1-catcher-09/17/2018 223:323360381-catcher-09/17/2018 223:3233:336038 tree 1-catcher-09/17/2018 223:3233:38 false

可以看到,item1、item2和item3的属性是相同的,item1和item2实际上是同一个对象。项目3和项目1不一样。

用法3

除了DefaultObjectPool之外,DefaultObjectPoolProvider还可以创建一个对象池。

创建对象池必须与策略不可分割,因此我们仍然使用自己定义的DemoPooledObjectPolicy。

var DefaultProvider=new DefaultObjectPoolProvider();var policy=new DemopooledObjectPoLicy();//默认最大值详细信息是环境。ProcessorCount * 2ObjectPoolDemo池=defaultProvider。创建(策略);item1=池。get();游泳池。退货(项目1);item2=池。get();控制台。WriteLine($'{item1。Id}-{item1。名称}-{item1。create Timote } ');控制台。WriteLine($'{item2。Id}-{item2。名称}-{item2。create Timote } ');控制台。write line(item 1==item 2);item3=池。get();控制台。WriteLine($'{item3。Id}-{item3。名称}-{item3。create Timote } ');控制台。write line(item 3==item 2);使用提供程序创建对象池时,不能指定要保留的最大对象数,只能指定默认环境。可以使用处理器计数* 2。

后一种用法与用法2相同。

您可以看到项目1和项目2是同一个对象。当从对象池中取出一个对象时,会取出第一个对象,所以如果您将其退回并再次取出,您仍然会得到原始的第一个对象。

项目3直接取自对象池,但没有再次创建,因为这里的对象池维护多个对象,而不是用法2中只有一个对象,所以它直接取自池。

以下是输出

1-catcher-09/17/2018 22:383360341-catcher-09/17/2018 22:38:336034 tree 1-catcher-09/17/2018 223:383360344 false

而用法2,本质是一样的。

用法4

上面的用法好像和我们平时用的不太一样。我们仍然需要依靠注射。

然后让我们最后看看如何组合依赖注入。当然,这里的本质还是离不开两个东西:政策和提供者。

IServiceCollection services=new service collection();服务。AddSingletonObjectPoolProvider,DefaultObjectPoolProvider();服务。AddSingleton(s={ var provider=s . GetRequiredServiceObjectPoolProvider();返回提供程序。创建(新的DemoPoleDobjectPoLicy());});服务提供商服务提供商=服务。BuildServiceProvider();var pool=serviceProvider。GetServiceObjectPoolDemo();item1=池。get();游泳池。退货(项目1);item2=池。get();控制台。WriteLine($'{item1。Id}-{item1。名称}-{item1。create Timote } ');控制台。WriteLine($'{item2。Id}-{item2。名称}-{item2。create Timote } ');控制台。write line(item 1==item 2);item3=池。get();控制台。WriteLine($'{item3。Id}-{item3。名称}-{item3。create Timote } ');控制台。write line(item 3==item 2);我们需要先注册提供程序,然后直接用它的实例创建一个对象池。

如果您想在其他地方使用它,可以通过构造函数注入它。

这里的结果和以前一样,没什么好说的。

摘要

在这些用法中,最常用的应该是用法4。

然而,不管使用什么,我们都需要理解,对象池离不开三个人:池、策略和提供者。

有了这三个,也许我们可以为所欲为。

当然也提供了一些特别的东西,有兴趣的可以看看。

泄漏跟踪对象池

StringBuilderPooledObjectPolicy

最后,本文以脑图结束。

以上是中对象池各种用法的详细说明。NET Core由边肖介绍,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!

版权声明:中对象池各种用途的详细说明 净核心是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。