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 }