C#中设计一个 ListPool 的方案

Posted 假于物つ点进客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#中设计一个 ListPool 的方案相关的知识,希望对你有一定的参考价值。

1、回顾一下有关List的几个知识点。

    点1: 注意理解 Capacity 与 Count 的不同之处。

    点2: 执行 TrimExcess() 方法可将容量设置为 List 中元素的实际数目。

    点3: List的 Capacity (注意理解与 Count 的不同之处)扩充是以 4 的倍数来扩充的。

    点4: 执行完 Clear() 方法后,Capacity 是不会变化的。

1 List<int> list = new List<int>();
2 Console.WriteLine(list.Capacity);   // 0
3 list.Add(1);
4 Console.WriteLine(list.Capacity);   // 4

2、ListPool方案:

  1 using System;
  2 using System.Collections.Generic;
  3 
  4 public interface IListPoolBase
  5 {
  6     void DoClear(int nowSeconds);
  7 }
  8 
  9 public class ListPoolItem<T> : IListPoolBase
 10 {
 11     static int intervalTime = 30;  //清理池子的时间间隔(单位 : 秒)
 12     public List<List<T>> pool;      //用List而不用Stack是因为在回收的时候,当pool达到上限的时候,要替换到 Capacity 最大的那个,用 Stack 无法自主替换
 13     public int lastUsedSeconds;
 14 
 15     public ListPoolItem(int initSize)
 16     {
 17         lastUsedSeconds = (int)(DateTime.Now.Ticks / TimeSpan.TicksPerSecond);
 18         pool = new List<List<T>>(initSize);
 19     }
 20 
 21     //长时间不用,清理一下池子
 22     public void DoClear(int nowSeconds)
 23     {
 24         if (pool.Count > 0)
 25         {
 26             int durationNotUse = nowSeconds - lastUsedSeconds;
 27             if (durationNotUse >= intervalTime)
 28             {
 29                 pool.Clear();
 30             }
 31         }
 32     }
 33 
 34     public void Use()
 35     {
 36         lastUsedSeconds = (int)(DateTime.Now.Ticks / TimeSpan.TicksPerSecond);
 37     }
 38 }
 39 
 40 public static class ListPool<T>
 41 {
 42     public static int maxPoolSize = 4;
 43     static ListPoolItem<T> poolItem;
 44 
 45     static ListPool()
 46     {
 47         poolItem = new ListPoolItem<T>(maxPoolSize);
 48         ListPoolManager.Register(poolItem);
 49     }
 50 
 51     public static List<T> Get()
 52     {
 53         lock (poolItem)
 54         {
 55             poolItem.Use();
 56             List<List<T>> pool = poolItem.pool;
 57             int poolSize = pool.Count;
 58             if (poolSize > 0)
 59             {
 60                 List<T> list = pool[poolSize - 1];
 61                 pool.RemoveAt(poolSize - 1);
 62                 return list;
 63             }
 64             else
 65             {
 66                 return new List<T>();
 67             }
 68         }
 69     }
 70 
 71     public static void Release(ref List<T> list)
 72     {
 73         if (null == list) return;
 74         lock (poolItem)
 75         {
 76             poolItem.Use();
 77             List<List<T>> pool = poolItem.pool;
 78             List<T> _list = list;
 79             list = null;
 80             if (pool.Contains(_list))
 81                 return;
 82             _list.Clear();
 83 
 84             //当_List的开辟的容量过大的时候,需要考虑到无用的容量,之所以加这个判断而不是直接清除,是为了避免反复的开辟空间
 85             if (_list.Capacity >= 4096)
 86             {
 87                 _list.TrimExcess();
 88             }
 89 
 90             int poolSize = pool.Count;
 91             //当pool的容量达到最大的时候,替换掉容量最大的那个
 92             if (poolSize >= maxPoolSize)
 93             {
 94                 int replaceIndex = -1;
 95                 int maxCapacity = _list.Capacity;
 96                 for (int i = 0; i < poolSize; ++i)
 97                 {
 98                     List<T> curList = pool[i];
 99                     if (curList.Capacity > maxCapacity)
100                     {
101                         replaceIndex = i;
102                         maxCapacity = curList.Capacity;
103                     }
104                 }
105 
106                 if (replaceIndex >= 0)
107                 {
108                     pool[replaceIndex] = _list;
109                 }
110                 return;
111             }
112 
113             pool.Add(_list);
114         }
115     }
116 }
117 
118 //检测ListPool的使用情况
119 public static class ListPoolManager
120 {
121     static int _timerMS;
122     static int _minTriggerTimeMS = 3000;  //执行检测的时间间隔
123     static List<IListPoolBase> listPool = new List<IListPoolBase>();
124 
125     public static void Register(IListPoolBase poolItem)
126     {
127         listPool.Add(poolItem);
128     }
129 
130     //在主线程中做检测
131     public static void DoTracer(int deltaTimeMS)
132     {
133         _timerMS += deltaTimeMS;
134         //降低执行检测的频率
135         if (_timerMS < _minTriggerTimeMS)
136             return;
137 
138         _timerMS = 0;
139 
140         int nowSeconds = (int)(DateTime.Now.Ticks / TimeSpan.TicksPerSecond);
141         for (int i = 0; i < listPool.Count; ++i)
142         {
143             listPool[i].DoClear(nowSeconds);
144         }
145     }
146 }

以上是关于C#中设计一个 ListPool 的方案的主要内容,如果未能解决你的问题,请参考以下文章

C# ListPool 缓存数据结构

水晶报表,c#中,怎么在Winform应用程序中设计功能载入rpt水晶报表文件?

在 Excel 中设计用户定义函数? [关闭]

在 Xcode 的 IB 中设计一个 SCNNode

如何复制故事板中设计的 UIView?

在 Visual Studio 中设计通用表单