您好,登录后才能下订单哦!
这篇文章主要讲解了“.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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。