.NET Core对象池的示例分析
这篇文章主要介绍了.NET Core对象池的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
一、 IPooledObjectPolicy
池化对象策略的IPooledObjectPolicy
public interface IPooledObjectPolicy{ T Create(); bool Return(T obj);}public abstract class PooledObjectPolicy : IPooledObjectPolicy { protected PooledObjectPolicy(){} public abstract T Create(); public abstract bool Return(T obj);}
我们默认使用的是如下这个DefaultPooledObjectPolicy
public class DefaultPooledObjectPolicy: PooledObjectPolicy where T: class, new(){ public override T Create() => Activator.CreateInstance (); public override bool Return(T obj) => true;}
二、ObjectPool
对象池通过ObjectPool
public abstract class ObjectPoolwhere T: class{ protected ObjectPool(){} public abstract T Get(); public abstract void Return(T obj);}
DefaultObjectPool
我们默认使用的对象池体现为一个DefaultObjectPool

如下面的代码片段所示,DefaultObjectPool
public class DefaultObjectPool: ObjectPool where T : class{ private protected T _firstItem; private protected readonly ObjectWrapper[] _items; … private protected struct ObjectWrapper { public T Element; }}
DefaultObjectPool
public class DefaultObjectPool: ObjectPool where T : class{ private protected T _firstItem; private protected readonly ObjectWrapper[] _items; private protected readonly IPooledObjectPolicy _policy; private protected readonly bool _isDefaultPolicy; private protected readonly PooledObjectPolicy _fastPolicy; public DefaultObjectPool(IPooledObjectPolicy policy) : this(policy, Environment.ProcessorCount * 2) {} public DefaultObjectPool(IPooledObjectPolicy policy, int maximumRetained) { _policy = policy ; _fastPolicy = policy as PooledObjectPolicy ; _isDefaultPolicy = IsDefaultPolicy(); _items = new ObjectWrapper[maximumRetained - 1]; bool IsDefaultPolicy() { var type = policy.GetType(); return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(DefaultPooledObjectPolicy<>); } } [MethodImpl(MethodImplOptions.NoInlining)] private T Create() => _fastPolicy?.Create() ?? _policy.Create();}
从第二个构造函数的定义可以看出,指定的IPooledObjectPolicy
如下所示的是重写的Get和Return方法的定义。用于提供池化对象的Get方法很简单,它会采用原子操作使用Null将_firstItem字段表示的对象"替换"下来,如果该字段不为Null,那么将其作为返回的对象,反之它会遍历数组的每个ObjectWrapper对象,并使用Null将其封装的对象"替换"下来,第一个成功替换下来的对象将作为返回值。如果所有ObjectWrapper对象封装的对象都为Null,意味着所有对象都被"借出"或者尚未创建,此时返回创建的新对象了。
public class DefaultObjectPool: ObjectPool where T : class{ 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; } 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) {} } } } …}
将对象释放会对象池的Return方法也很好理解。首先它需要判断指定的对象能否释放会对象池中,如果使用的是默认的池化对象策略,答案是肯定的,否则只能通过调用IPooledObjectPolicy
在确定指定的对象可以释放回对象之后,如果_firstItem字段为Null,Return方法会采用原子操作使用指定的对象将其"替换"下来。如果该字段不为Null或者原子替换失败,该方法会便利数组的每个ObjectWrapper对象,并采用原子操作将它们封装的空引用替换成指定的对象。整个方法会在某个原子替换操作成功或者整个便利过程结束之后返回。
DefaultObjectPool
DisposableObjectPool
通过前面的示例演示我们知道,当池化对象类型实现了IDisposable接口的情况下,如果某个对象在回归对象池的时候,对象池已满,该对象将被丢弃。与此同时,被丢弃对象的Dispose方法将立即被调用。但是这种现象并没有在DefaultObjectPool
internal sealed class DisposableObjectPool: DefaultObjectPool , IDisposable where T : class{ private volatile bool _isDisposed; public DisposableObjectPool(IPooledObjectPolicy policy) : base(policy) {} public DisposableObjectPool(IPooledObjectPolicy policy, int maximumRetained) : base(policy, maximumRetained) {} public override T Get() { if (_isDisposed) { throw new ObjectDisposedException(GetType().Name); } return base.Get(); } public override void Return(T obj) { if (_isDisposed || !ReturnCore(obj)) { DisposeItem(obj); } } private bool ReturnCore(T obj) { bool returnedToPool = false; if (_isDefaultPolicy || (_fastPolicy?.Return(obj) ?? _policy.Return(obj))) { if (_firstItem == null && Interlocked.CompareExchange(ref _firstItem, obj, null) == null) { returnedToPool = true; } else { var items = _items; for (var i = 0; i < items.Length && !(returnedTooPool = Interlocked.CompareExchange(ref items[i].Element, obj, null) == null); i++) {} } } return returnedTooPool; } public void Dispose() { _isDisposed = true; DisposeItem(_firstItem); _firstItem = null; ObjectWrapper[] items = _items; for (var i = 0; i < items.Length; i++) { DisposeItem(items[i].Element); items[i].Element = null; } } private void DisposeItem(T item) { if (item is IDisposable disposable) { disposable.Dispose(); } }}
从上面代码片段可以看出,DisposableObjectPool
三、ObjectPoolProvider
表示对象池的ObjectPool
public abstract class ObjectPoolProvider{ public ObjectPool Create() where T : class, new() => Create(new DefaultPooledObjectPolicy()); public abstract ObjectPool Create(IPooledObjectPolicy policy) where T : class;} 在前面的示例演示中,我们使用的是如下这个DefaultObjectPoolProvider类型。如代码片段所示,DefaultObjectPoolProvider派生于抽象类ObjectPoolProvider,在重写的Create
public class DefaultObjectPoolProvider : ObjectPoolProvider{ public int MaximumRetained { get; set; } = Environment.ProcessorCount * 2; public override ObjectPool Create(IPooledObjectPolicy policy) => typeof(IDisposable).IsAssignableFrom(typeof(T)) ? new DisposableObjectPool(policy, MaximumRetained) : new DefaultObjectPool(policy, MaximumRetained);} DefaultObjectPoolProvider类型定义了一个标识对象池大小的MaximumRetained属性,采用处理器数量的两倍作为默认容量也体现在这里。这个属性并非只读,所以我们可以利用它根据具体需求调整提供对象池的大小。在ASP.NET应用中,我们基本上都会采用依赖注入的方式利用注入的ObjectPoolProvider对象来创建针对具体类型的对象池。我们在《编程篇》还演示了另一种创建对象池的方式,那就是直接调用ObjectPool类型的静态Create
public static class ObjectPool{ public static ObjectPool Create(IPooledObjectPolicy policy) where T: class, new() => new DefaultObjectPoolProvider().Create(policy ?? new DefaultPooledObjectPolicy());} 到目前为止,我们已经将整个对象池的设计模型进行了完整的介绍。总得来说,这是一个简单、高效并且具有可扩展性的对象池框架,该模型涉及的几个核心接口和类型体现在如下图所示的UML中。
感谢你能够认真阅读完这篇文章,希望小编分享的".NET Core对象池的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!