zoukankan      html  css  js  c++  java
  • 在C#中实现简单的对象池

    当我们频繁创建删除大量对象的时候,对象的创建删除所造成的开销就不容小觑了。为了提高性能,我们往往需要实现一个对象池作为Cache:使用对象时,它从池中提取。用完对象时,它放回池中。从而减少创建对象的开销。

    由于.net BCL库中并没有对象池的标准实现,因此需要我们自己去实现。好在实现功能简单的对象池并不麻烦,一般几十行代码就能实现。需要注意的一点是,对象池大多是需要支持多线程访问的,因此需要考虑线程安全问题。

    在.Net 4.0后,BCL在System.Collections.Concurrent名字空间下引入了一系列线程安全的对象,微软甚至在MSDN上给了一个通过实现对象池的简单示例:How to: Create an Object Pool by Using a ConcurrentBag.

    这个例子本身没有什么问题,但如果放在实际生产中就觉得有点简单过头了,一般还需要加上容量限制和重用时进行reset操作。这里我就稍微将其改了下: 

     1 public class ObjectPool<T>
     2     {
     3         ConcurrentBag<T> buffer;
     4         Func<T> createFunc;
     5         Action<T> resetFunc;
     6 
     7         public ObjectPool(Func<T> createFunc, Action<T> resetFunc, int capacity)
     8         {
     9             Contract.Assume(createFunc != null);
    10             Contract.Assume(capacity > 0);
    11 
    12             this.buffer = new ConcurrentBag<T>();
    13             this.createFunc = createFunc;
    14             this.resetFunc = resetFunc;
    15 
    16             this.Capacity = capacity;
    17         }
    18 
    19         public int Capacity { get; private set; }
    20         public int Count { get { return buffer.Count; } }
    21 
    22         /// <summary>
    23         /// 申请对象
    24         /// </summary>
    25         public T GetObject()
    26         {
    27             var obj = default(T);
    28 
    29             if (!buffer.TryTake(out obj))
    30                 return createFunc();
    31             else
    32                 return obj;
    33         }
    34 
    35         /// <summary>
    36         /// 释放对象
    37         /// </summary>
    38         public void PutObject(T obj)
    39         {
    40             Contract.Assume(obj != null);
    41 
    42             if (Count >= Capacity)        //超过容量了,不再需要
    43                 return;
    44 
    45             if (resetFunc != null)
    46                 resetFunc(obj);
    47 
    48             buffer.Add(obj);
    49         }
    50     }
    View Code

    需要注意的是,我这里的实现并没有完全确保Capacity的绝对性:当两个线程同时往一个即将到达上限的对象池中放置对象时,可能都会成功。因为我觉得这个是没有太大必要的,感兴趣的朋友可以把它改下。

  • 相关阅读:
    正则表达式验证日期(多种日期格式)——转载
    NPOI导出Excel——精简版
    Ubuntu下安装部署.NET Core多版本环境
    搭建 nuget 私用库 BaGet
    ubuntu 监听端口
    搭建npm 私用库 verdaccio
    pgsql 性能测试 pgbench
    docker-compose 创建网络
    安装 docker-compose 启动
    dotnet sdk安装以及环境变量设置 Ubuntu 18.04 LTS
  • 原文地址:https://www.cnblogs.com/TianFang/p/3411399.html
Copyright © 2011-2022 走看看