.Net对象池扩展

什么是对象池?

对象池就是一种为对象提供可复用性能力的软件设计思路。简单而言就是将创建得对象放置到一个容器中(池),需要的时候从容器中获取,使用后归还到容器。保证对象可以被重复使用,进而节省频繁创建对象的性能开销。

.NET Core中的对象池

在.NET Core已经提供了对象池的实现,主要有三大对象:ObjectPoolProvider、ObjectPool、IPooledObjectPolicy

  • ObjectPoolProvider:对象池提供器。用于构建对象池,指定对象池容量【默认电脑处理器数量的2倍】,默认创建DefaultObjectPool,当对象实现IDisposable接口时创建DisposableObjectPool
  • ObjectPool:对象池,提供对象的获取和归还。
  • IPooledObjectPolicy 用于管理池对象的策略。可以指定池对象的创建和归还方式。
    三个核心组件关系如下图:

示例:

TeacherObjectPoolPolicy
public class TeacherObjectPoolPolicy : IPooledObjectPolicy<Teacher>
{
    public Teacher Create()
    {
        var id = Guid.NewGuid().ToString("N");
        return new Teacher()
        {
            Id = id,
            Name = "老师"
        }; 
    }

    public bool Return(Teacher obj)
    {
        return true;
    }
}
服务注册
var builder = WebApplication.CreateBuilder(args);
//对象池
builder.Services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
builder.Services.AddSingleton(serviceProvider =>
{
    var objectPoolProvider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
    return objectPoolProvider.Create(new TeacherObjectPoolPolicy());
});
var app = builder.Build();
使用
var policy = new TeacherObjectPoolPolicy();
//指定对象创建策略,对象池容量为2
var objectPool = new DefaultObjectPool<Teacher>(policy, 2);
var teacher1 = objectPool.Get();
var teacher2 = objectPool.Get();
Console.WriteLine(teacher1.Id);
Console.WriteLine(teacher2.Id);
Console.WriteLine(teacher1.Equals(teacher2));
objectPool.Return(teacher1);
var teacher3 = objectPool.Get();
Console.WriteLine(teacher3.Id);
//teacher3复用了teacher1对象
Console.WriteLine(teacher1.Equals(teacher3));

对象池扩展

简化对象池的适用,通过注入方式使用对象池,使用完成后自动释放归还

ObjectPoolManager
public interface IObjectPoolManager : IDisposable
{
    T Get<T>() where T : class;

    void Return<T>(T obj) where T : class;
}

public class ObjectPoolManager : IObjectPoolManager
{
    private readonly IServiceProvider _services;
    private readonly Dictionary<string, IAutoDisposableObjectPool> _dicObjectPool;
    public ObjectPoolManager(IServiceProvider services)
    {
        _services = services;
        _dicObjectPool = new Dictionary<string, IAutoDisposableObjectPool>();
    }

    public T Get<T>() where T : class
    {
        if (_dicObjectPool.TryGetValue(typeof(T).FullName, out IAutoDisposableObjectPool objectPool))
        {
            return objectPool.Get() as T;
        } 
        objectPool = new AutoDisposableObjectPool<T>(_services.GetService(typeof(ObjectPool<T>)) as ObjectPool<T>);
        _dicObjectPool[typeof(T).FullName] = objectPool;
        return objectPool.Get() as T;
    }

    public void Return<T>(T obj) where T : class
    {
        if (!_dicObjectPool.TryGetValue(typeof(T).FullName, out IAutoDisposableObjectPool objectPool))
            return;
        objectPool.Return(obj);
    }

    public void Dispose()
    {
        foreach (var objectPool in _dicObjectPool)
        {
            objectPool.Value.Dispose();
        }
    }

    private class AutoDisposableObjectPool<T> : IAutoDisposableObjectPool where T : class
    {
        private readonly ObjectPool<T> _objectPool;
        private readonly IList<T> _items;

        public AutoDisposableObjectPool(ObjectPool<T> objectPool)
        {
            _objectPool = objectPool;
            _items = new List<T>();
        }

        public object Get()
        {
            var obj = _objectPool.Get();
            _items.Add(obj);
            return obj;
        }

        public void Return(object obj)
        {
            Return(obj as T);
        }

        private void Return(T obj)
        {
            _objectPool.Return(obj);
            _items.Remove(obj);
        }

        public void Dispose()
        {
            var returnList = new List<T>(_items);
            foreach (var item in returnList)
            {
                Return(item);
            }
        }
    }

    private interface IAutoDisposableObjectPool : IDisposable
    {
        object Get();

        void Return(object obj);
    }

服务注册
var builder = WebApplication.CreateBuilder(args);
//注册IObjectPoolManager为瞬时,请求结束自动归还对象
builder.Services.AddTransient<IObjectPoolManager, ObjectPoolManager>();
var app = builder.Build();
使用
public class ObjectPoolController : Controller
{
    //构造函数注入IObjectPoolManager 
    private readonly IObjectPoolManager _objectPoolManager;
    public ObjectPoolController(IObjectPoolManager objectPoolManager)
    {
        _objectPoolManager = objectPoolManager;
    }

    public async Task Test()
    {
        //多次获取没有归还返回,获取到的不同对象
        for (int i = 0; i < 5; i++)
        {
            var techer = _objectPoolManager.Get<Teacher>();
            Console.WriteLine(techer.Id);
        }
        Console.WriteLine("*******************");
        //获取对象后手动归还,再次获取时同一对象
        var teacher1 = _objectPoolManager.Get<Teacher>();
        Console.WriteLine(teacher1.Id);
        _objectPoolManager.Return(teacher1);
        var teacher2 = _objectPoolManager.Get<Teacher>();
        Console.WriteLine(teacher2.Id);
        Console.WriteLine(teacher2.Equals(teacher2));
    }
}
第一次请求结束后所有的对象全部归还到对象池中,第二次获取时与第一次对应一样。

posted @   CharlesQ  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示