C# | 对象池

简介: 当我们在做软件开发时经常会需要创建很多的相同且特殊的对象,比如线程、内存、数据库连接、文件句柄等,这类特殊对象有着占用IO资源、创建或销毁的开销大等特点,会导致系统的性能下降和资源浪费。而对象池的出现就是为了解决此类问题,使用对象池来管理这些对象让它们可以被重复使用,从而提高效率。

image.png

对象池

@[toc]

前言

当我们在做软件开发时经常会需要创建很多的相同且特殊的对象,比如线程、内存、数据库连接、文件句柄等,这类特殊对象有着占用IO资源、创建或销毁的开销大等特点,会导致系统的性能下降和资源浪费。而对象池的出现就是为了解决此类问题,使用对象池来管理这些对象让它们可以被重复使用,从而提高效率。


什么是对象池

那么什么是对象池呢?
就是在一个池中预先创建n个对象,当需要使用的时候就从这个池中获取一个实例,并使用完毕后并不销毁释放,而是再将其放回池中,以便可以多次重复使用。

对象池的优点

对象池可以大幅度的减少对象创建和销毁的过程,从而提高程序的运行效率和资源的利用率。此外对象池还可以准确的控制对象创建的数量,因此对于程序的稳定性也有极大助益。

对象池的缺点

对象池的劣势在于它的机制就已经决定了对象池中会有一定数量的对象持续占用内存,如果池中保留的对象的数量过多,可能会导致系统的内存不足,也可能导致其他进程无法拿到系统资源。
还有就是对象池需要进行对象的管理和维护,对于内存池中保留的对象的个数如何取值就需要结合软件和硬件的实际情况进行综合考量了,需要在运行效率和资源消耗上取得平衡。如果管理不当可能会适得其反。


实现思路

设计对象池的思路主要是确定对象池的大小、对象的创建方式、对象的回收方式以及线程安全等问题。通常情况下,我们需要在程序初始化时创建一定数量的对象,并将这些对象存储在对象池中。
当需要使用对象时,从对象池中获取一个可用的对象,使用完毕后将其放回对象池中。如果对象池中的对象数量不足,可以根据需要动态地创建新的对象并添加到对象池中。

简单的对象池示例

下面是一个简易的对象池例子:

public class ObjectPool<T>
{
   
   
    private readonly Func<T> _objectFactory;
    private readonly ConcurrentBag<T> _objects;

    public ObjectPool(Func<T> objectFactory)
    {
   
   
        _objectFactory = objectFactory;
        _objects = new ConcurrentBag<T>();
    }

    public T GetObject()
    {
   
   
        T obj;
        if (_objects.TryTake(out obj))
        {
   
   
            return obj;
        }
        return _objectFactory();
    }

    public void PutObject(T obj)
    {
   
   
        _objects.Add(obj);
    }
}

上面的代码中使用了ConcurrentBag类来实现线程安全的对象管理。
在创建ObjectPool对象时,需要传入一个用于创建对象的委托函数。
当需要获取对象时,先尝试从对象池中获取一个可用的对象,如果对象池中没有可用的对象,则根据委托函数创建一个新的对象。使用完毕后,将对象放回对象池中。

优化:增加保留个数限制

接下来优化一下这个例子,添加一个值限制对象池中保留对象的个数,超出限制的对象会被释放掉。

public class ObjectPool<T>
{
   
   
    private readonly Func<T> _objectFactory;
    private readonly ConcurrentBag<T> _objects;
    private readonly int _maxSize;

    public ObjectPool(Func<T> objectFactory, int maxSize)
    {
   
   
        _objectFactory = objectFactory;
        _objects = new ConcurrentBag<T>();
        _maxSize = maxSize;
    }

    public T GetObject()
    {
   
   
        T obj;
        if (_objects.TryTake(out obj))
        {
   
   
            return obj;
        }
        return _objectFactory();
    }

    public void PutObject(T obj)
    {
   
   
        if (_objects.Count < _maxSize)
        {
   
   
            _objects.Add(obj);
        }
        else
        {
   
   
            IDisposable disposable = obj as IDisposable;
            if (disposable != null)
            {
   
   
                disposable.Dispose();
            }
        }
    }
}

新增了一个名为_maxSize的属性来表示对象池中最多可以保留的对象个数。在PutObject方法中,我们判断当前对象池中的对象数量是否已经达到了最大值,如果是,则释放掉超出限制的对象,否则将对象加入到对象池中。为了保证释放对象时的安全性和可靠性,我们将对象转换为IDisposable接口,如果对象实现了IDisposable接口,则调用其Dispose方法进行释放。

这样,我们就成功地为对象池添加了一个值限制,可以避免对象池中的对象数量过多导致内存溢出和性能下降的问题。当对象池中的对象数量超过限制时,我们可以选择释放对象或者将对象丢弃掉,以保证程序的稳定性和可靠性。


结束语

通过使用对象池,我们可以大幅度减少对象的创建和销毁次数,从而提高程序的运行效率和资源的利用率。同时,我们也需要考虑对象池的大小和限制等问题,以保证程序的性能和可靠性。

在未来的文章中还会介绍其他相关的池,例如线程池、内存池等,更全面地讲解池的相关知识。

如果您觉得本文对您有所帮助,欢迎点赞收藏关注。谢谢!

禁止转载声明:
本文受到版权保护,未经作者许可,严禁转载。任何机构或个人不得以任何形式将本文用于商业用途或进行二次创作、复制、转载等行为。任何未经授权使用本文所涉及的任何内容,作者保留追究法律责任的权利。如需引用本文,请务必注明出处并获得作者的明确授权,感谢您的理解与支持!

相关文章
|
存储 Kubernetes 负载均衡
Kubeadm 初始化高可用 kubernetes v1.17.2集群 | 学习笔记
快速学习 Kubeadm 初始化高可用 kubernetes v1.17.2集群
Kubeadm 初始化高可用 kubernetes v1.17.2集群 | 学习笔记
|
域名解析 传感器 网络协议
DNS科普系列 :被动DNS(Passive DNS)
在DNS领域有一些“专有技术名词(俗称行业”黑话“),不熟悉DNS和相关应用的人可能不容易接触和理解他们。从这篇开始,我们将帮助大家梳理一些DNS专有名词,本期的专有名词是:被动DNS(Passive DNS)。
DNS科普系列 :被动DNS(Passive DNS)
|
存储 安全 JavaScript
【分布式技术专题】「授权认证体系」深度解析OAuth2.0协议的原理和流程框架实现指南(授权流程和模式)
在传统的客户端-服务器身份验证模式中,客户端请求服务器上访问受限的资源(受保护的资源)时,需要使用资源所有者的凭据在服务器上进行身份验证。资源所有者为了给第三方应用提供受限资源的访问权限,需要与第三方共享它的凭据。这就导致一些问题和局限:
1267 2
【分布式技术专题】「授权认证体系」深度解析OAuth2.0协议的原理和流程框架实现指南(授权流程和模式)
Linux CentOS 平台安装 rar unrar 命令
Linux CentOS 平台安装 rar unrar 命令
2429 0
|
监控 TensorFlow 算法框架/工具
阿里云超算:高性能容器方案实战之Singularity
除了自动化整合IaaS层硬件资源为用户提供云上HPC集群外,E-HPC还致力于巩固云上HPC服务的高可用性,先后推出了“集谛多维性能监控”、“低成本断点续算”等新特性,帮助用户更好、更省地使用云上HPC服务。本文主要介绍阿里云超算推出的弹性高性能容器方案以及在分子动力学领域和AI领域的实战案例。
10052 0
|
12月前
|
机器学习/深度学习 弹性计算 编解码
阿里云服务器ECS计算型c9i实例收费标准价格表:一年、1小时和1个月费用清单
阿里云ECS计算型c9i实例基于全新CIPU架构,搭载Intel Xeon Granite Rapids处理器,主频3.2GHz,性能稳定,适用于机器学习、视频编码、高性能计算等场景。支持按量付费(小时计费)和包年包月多种模式,提供从ecs.c9i.large到ecs.c9i.48xlarge共12种配置,vCPU从2核至192核,内存4GiB至384GiB,网络带宽最高64Gbps,云盘IOPS达80万。价格灵活,一年付、三年付享大幅折扣,适合不同业务需求。
1043 13
|
存储 分布式计算 算法
Java 大视界 -- Java 大数据在智能教育在线考试监考与作弊检测中的技术创新(193)
本文探讨了Java大数据技术在智能教育在线考试监考与作弊检测中的创新应用。随着在线考试的普及,作弊问题日益突出,传统监考方式难以应对。通过Java大数据技术,可实现考生行为分析、图像识别等多维度监控,提升作弊检测的准确性与效率。结合Hadoop与Spark等技术,系统能实时处理海量数据,构建智能监考体系,保障考试公平性,推动教育评价体系的数字化转型。
|
存储 消息中间件 前端开发
.NET常见的几种项目架构模式,你知道几种?
.NET常见的几种项目架构模式,你知道几种?
651 0
|
监控 关系型数据库 Go
《打造高可用PostgreSQL:策略与工具》
《打造高可用PostgreSQL:策略与工具》
686 0
|
Web App开发 搜索推荐 安全