架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12592|回复: 1

[.NET Core] .NET Core 中 Object Pool 详解

[复制链接]
发表于 2020-4-15 17:38:34 | 显示全部楼层 |阅读模式
Microsoft.Extensions.ObjectPool 是 ASP.NET Core 基础结构的一部分,该基础结构支持在内存中保留一组对象以供重复使用,而不是允许对对象进行垃圾回收。
如果要管理的对象是,则你可能需要使用对象池:

  • 分配/初始化成本高昂。
  • 表示某些有限资源。
  • 使用可预测和频繁。


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

举个最为简单,大家最为熟悉的例子,数据库连接池,就是复用数据库连接。

那么复用的意义在那里呢?

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

除了数据库连接,可能在不同的情景或需求下,还会有很多其他对象需要进行复用,这个时候就会有所谓的 Object Pool(对象池)。

小伙伴们应该也自己实现过类似的功能,或用ConcurrentBag,或用ConcurrentQueue,或用其他方案。

这也里分享一个在微软文档中的实现

How to: Create an Object Pool by Using a ConcurrentBag

https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/how-to-create-an-object-pool

当然,在.NET Core中,微软已经帮我们实现了一个简单的Object Pool。

首先,新建一个.net core的控制台项目,使用nuget命令添加如下包:

所有的代码如下:

用法一

e1.png

在创建pool之前,我们要先定义一个Policy。这里直接用自带的DefaultPooledObjectPolicy来构造。

对象池会有一个维护的最大数量,线程数。

通过pool对象的Get方法,从对象池中取出一个对象。

上面代码运行结果

#1-464d2e03-604d-4451-b68a-8a3a2abdfccc-itsvse.com-1/1/0001 12:00:00 AM
#2-70122aa0-a949-4c63-b878-321efe64c234-itsvse.com-1/1/0001 12:00:00 AM
#3-de717815-796a-4349-a571-047acc125104-itsvse.com-1/1/0001 12:00:00 AM
#4-3a404341-a560-47f7-a3b0-0d477a8ae17f-itsvse.com-1/1/0001 12:00:00 AM
#5-51c96126-d424-4b58-b07c-6408e6c4cea6-itsvse.com-1/1/0001 12:00:00 AM
#6-7ea4d596-fd2a-43b3-959a-9e48da58a758-itsvse.com-1/1/0001 12:00:00 AM
#7-6874c64b-532d-4f92-a4fb-ff472da574a1-itsvse.com-1/1/0001 12:00:00 AM
#8-ca767674-2c07-4f26-975f-4711a31d795d-itsvse.com-1/1/0001 12:00:00 AM
#9-a9cd1859-a919-46a0-ae5d-85b6d3d11ccb-itsvse.com-1/1/0001 12:00:00 AM
#10-fe89ed8b-4dfd-4eef-b876-b2a60ee50958-itsvse.com-1/1/0001 12:00:00 AM
这个结果说明,Object Pool 中的对象都是直接new出来的,并没有对一些属性进行贬值操作,这个时候往往没有太多实际意义。

因为DefaultPooledObjectPolicy本来就是直接new了一个对象出来,很多时候,这并不是我们所期望的!

要想符合我们实际的使用,就要自己定义一个Policy!

下面来看看用法2

用法二

Create方法就是用来创建Demo对象的,Return方法就是将Demo对象扔回Object Pool的(有借有还)。

e2.png

这里定义了对象池只保留一个对象。

由于从object pool中取出来之后,有一步还回去的操作,所以item1和item2应当是同一个对象。

从object pool中拿出了item2之后,它并没有还回去,所以object pool会基于我们定义的Policy去创建一个新的对象出来。

下面是用法2的输出结果:

985b3232-0a45-4115-8480-ad3d42c0ae10-itsvse.com-4/15/2020 3:31:15 AM
985b3232-0a45-4115-8480-ad3d42c0ae10-itsvse.com-4/15/2020 3:31:15 AM
True
8912424a-15c5-4891-b625-25b17eee5c8b-itsvse.com-4/15/2020 3:31:15 AM
False
可以看到item1,item2和item3的各个属性是一样的,并且item1和item2确实是同一个对象。item3和item1并不是同一个。


用法三

可以看到item1和item2是同一个对象。从Object Pool中取对象的时候,会取第一个,所以还回去后,再取的话,还是会取到原来的第一个。

e3.png

item3那里是直接从Object Pool中取出来的,没有再次创建,因为这里的Object Pool维护着多个对象,而不是用法2中的只有一个,所以它是直接从Pool中拿的。

下面是输出结果

f3cd5467-536b-4ffe-9c71-de53027b4869-itsvse.com-4/15/2020 3:33:58 AM
f3cd5467-536b-4ffe-9c71-de53027b4869-itsvse.com-4/15/2020 3:33:58 AM
True
b933b593-af6d-4ebe-b21b-e8784d124764-itsvse.com-4/15/2020 3:33:58 AM
False
和用法2,本质是一样的。

用法四

好像上面的用法,都不那么像我们正常使用的。我们还是需要依赖注入的。

那么我们最后就来看看怎么结合依赖注入吧。当然这里的本质还是离不开Policy和Provider这两个东西。

e4.png

我们首先需要完成对Provider的注册,然后直接拿它的实例去创建一个Object Pool即可。

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

这里的结果也是和前面一样的,没什么好多说的。

总结

但是无论那种用法,我们都需要了解,Object Pool离不开Pool,Policy和Provider这三个家伙。

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

当然,它还提供了几个特殊的东西,有兴趣的可以去看看。

LeakTrackingObjectPool

StringBuilderPooledObjectPolicy





上一篇:Web Services Enhancements (WSE) 3.0 介绍
下一篇:visual studio 2013如何查找替换多行的内容?
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2023-8-30 18:34:07 | 显示全部楼层
DefaultObjectPool 底层是用 ConcurrentQueue 线程安全队列实现,源码如下:


https://source.dot.net/#Microsoft.Extensions.ObjectPool/DefaultObjectPool.cs

QQ截图20230830183346.jpg
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2024-4-20 10:34

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表