德州市市政工程建设总公司网站,红河蒙自网站开发,南京制作网页公司,店名logo设计在线生成免费缓存#xff0c;在.Net系统开发中#xff0c;经常使用到。如果#xff0c;让你自己去实现#xff0c;你会怎么做呢。 开始编码前思考#xff1a; 1、肯定 是要 根据 key 去查询对应value#xff0c;so 应该是ListKeyValuePair 这类集合做缓存载体#xff1b; 2、… 缓存在.Net系统开发中经常使用到。如果让你自己去实现你会怎么做呢。 开始编码前思考 1、肯定 是要 根据 key 去查询对应valueso 应该是ListKeyValuePair 这类集合做缓存载体 2、肯定是要全局公用so 缓存的列表应该唯一 3、应该有支持并发的能力so 实现过程中肯定要加锁 4、应该可以支持过期自动 or 手动so 应该 可以添加过期时间 好的基于以上3点设计的类应该需要是单体单例模式查询、删除key时应该lock 缓存载体可以有定时清除过期缓存项的能力 1 public static class CacheHelper2 {3 private static int RestoreCacheCount 20000;4 private static DateTime LastRestoreCachTime;5 private static Dictionarystring, MyCacheEntity CacheEntryDictionary;6 private static readonly object objLock new object();7 8 static CacheHelper()9 {10 if (CacheEntryDictionary null)11 {12 lock (objLock)13 {14 if (CacheEntryDictionary null)15 {16 CacheEntryDictionary new Dictionarystring, MyCacheEntity();17 LastRestoreCachTime DateTime.Now;18 System.Threading.Tasks.Task.Factory.StartNew(() RestoreCache());19 }20 }21 }22 }23 24 public static void SetT(string key, T entity, double timeout)25 {26 if (string.IsNullOrEmpty(key))27 throw new ArgumentNullException(nameof(key));28 if (entity null)29 throw new ArgumentNullException(nameof(entity));30 var expiredTime DateTime.Now.AddSeconds(timeout);31 lock (objLock)32 {33 if (DateTime.Now.Subtract(expiredTime).TotalSeconds 0)34 {35 if (CacheEntryDictionary.ContainsKey(key))36 CacheEntryDictionary.Remove(key);37 }38 else39 {40 CacheEntryDictionary[key] new MyCacheEntity { Value entity, ExpiredTime expiredTime };41 }42 }43 }44 45 public static T GetT(string key)46 {47 if (string.IsNullOrEmpty(key))48 throw new ArgumentNullException(nameof(key));49 var value default(T);50 lock (objLock)51 {52 var exist CacheEntryDictionary.ContainsKey(key);53 if (!exist) return value;54 var obj CacheEntryDictionary[key];55 if (obj null)56 {57 CacheEntryDictionary.Remove(key);58 return value;59 }60 if (obj.ExpiredTime DateTime.MinValue || DateTime.Now.Subtract(obj.ExpiredTime).TotalSeconds 0)61 {62 CacheEntryDictionary.Remove(key);63 return value;64 }65 return (T)Convert.ChangeType(obj.Value, typeof(T));66 }67 }68 69 public static void Remove(string key)70 {71 if (string.IsNullOrEmpty(key))72 throw new ArgumentNullException(nameof(key));73 try74 {75 lock (objLock)76 {77 var exist CacheEntryDictionary.ContainsKey(key);78 if (!exist) return;79 CacheEntryDictionary.Remove(key);80 }81 }82 catch (Exception e)83 {84 throw e;85 }86 }87 88 public static void Clear()89 {90 try91 {92 lock (objLock)93 {94 CacheEntryDictionary.Clear();95 LastRestoreCachTime DateTime.Now;96 }97 }98 catch (Exception e)99 {
100 throw e;
101 }
102 }
103
104 public static int Count CacheEntryDictionary?.Count ?? 0;
105
106 private static void RestoreCache()
107 {
108 while (true)
109 {
110 if (CacheEntryDictionary.Keys.Count 1) return;
111 try
112 {
113 bool isEnter false;
114 Monitor.TryEnter(CacheEntryDictionary, 1000, ref isEnter);
115 if (isEnter)
116 {
117 if (CacheEntryDictionary.Count RestoreCacheCount DateTime.Now.Subtract(LastRestoreCachTime).TotalMinutes 1)
118 {
119 var keys CacheEntryDictionary.Where(m m.Value.ExpiredTime DateTime.Now).Select(m m.Key).ToList();
120 foreach (var key in keys)
121 {
122 CacheEntryDictionary.Remove(key);
123 }
124 LastRestoreCachTime DateTime.Now;
125 }
126 }
127 }
128 finally
129 {
130 Monitor.Exit(CacheEntryDictionary);
131 }
132 Thread.Sleep(1000 * 6);
133 }
134 }
135 }
136 public class MyCacheEntity
137 {
138 public object Value { get; set; }
139 public DateTime ExpiredTime { get; set; }
140 } 如果想要 key 不区分大小写可以 在构造函数中 设置 CacheEntryDictionary new Dictionarystring, MyCacheEntity(StringComparer.OrdinalIgnoreCase); 你可能会有疑问为什么不用 线程安全的字典 ConcurrentDictionary 呢 当然可以将 Dictionary 改为 ConcurrentDictionary 没有任何问题只是我想要自己手动实现加减速的过程ConcurrentDictionary 字典内部也是调用Monitor 进行的加减锁的过程 如果想要在缓存中实现 缓存文件并且文件内容改变同步修改缓存的内容呢 修改 以上方法 加入 1、添加缓存文件 2、刷新缓存文件内容定时过期、监控文件内容更改等 相关代码 1 public static class CacheHelper2 {3 private static int RestoreCacheCount 20000;4 private static DateTime LastRestoreCachTime;5 private static Dictionarystring, MyCacheEntity CacheEntryDictionary;6 private static readonly object objLock new object();7 private static Dictionarystring, MyCacheEntity FileCacheEntryDictionary;8 9 static CacheHelper()10 {11 if (CacheEntryDictionary null)12 {13 lock (objLock)14 {15 if (CacheEntryDictionary null)16 {17 CacheEntryDictionary new Dictionarystring, MyCacheEntity(StringComparer.OrdinalIgnoreCase);18 LastRestoreCachTime DateTime.Now;19 System.Threading.Tasks.Task.Factory.StartNew(() RestoreCache());20 }21 if (FileCacheEntryDictionary null)22 {23 FileCacheEntryDictionary new Dictionarystring, MyCacheEntity();24 System.Threading.Tasks.Task.Factory.StartNew(() ReFreshFileCache());25 }26 }27 }28 }29 30 public static void SetT(string key, T entity, double timeout)31 {32 if (string.IsNullOrEmpty(key))33 throw new ArgumentNullException(nameof(key));34 if (entity null)35 throw new ArgumentNullException(nameof(entity));36 var expiredTime DateTime.Now.AddSeconds(timeout);37 lock (objLock)38 {39 if (DateTime.Now.Subtract(expiredTime).TotalSeconds 0)40 {41 if (CacheEntryDictionary.ContainsKey(key))42 CacheEntryDictionary.Remove(key);43 }44 else45 {46 CacheEntryDictionary[key] new MyCacheEntity { Value entity, ExpiredTime expiredTime };47 }48 }49 }50 51 public static void SetFile(string key, string filePath, Encoding encoding, double timeout)52 {53 if (string.IsNullOrEmpty(key))54 throw new ArgumentNullException(nameof(key));55 if (!File.Exists(filePath))56 throw new FileNotFoundException(filePath);57 var expiredTime DateTime.Now.AddSeconds(timeout);58 lock (objLock)59 {60 if (DateTime.Now.Subtract(expiredTime).TotalSeconds 0)61 {62 if (CacheEntryDictionary.ContainsKey(key))63 CacheEntryDictionary.Remove(key);64 }65 else66 {67 FileInfo fileInfo new FileInfo(filePath);68 string value null;69 using (var stream new StreamReader(filePath, encoding))70 {71 value stream.ReadToEnd();72 }73 CacheEntryDictionary[key] new MyCacheEntity74 {75 Value value,76 ExpiredTime expiredTime77 };78 FileCacheEntryDictionary[key] new MyCacheEntity79 {80 Value new FileCacheOption81 {82 FilePath filePath,83 FileSize fileInfo.Length,84 LastWriteTime fileInfo.LastWriteTime,85 Encoding encoding86 },87 ExpiredTime expiredTime88 };89 }90 }91 }92 93 public static T GetT(string key)94 {95 if (string.IsNullOrEmpty(key))96 throw new ArgumentNullException(nameof(key));97 var value default(T);98 lock (objLock)99 {
100 var exist CacheEntryDictionary.ContainsKey(key);
101 if (!exist) return value;
102 var obj CacheEntryDictionary[key];
103 if (obj null)
104 {
105 CacheEntryDictionary.Remove(key);
106 return value;
107 }
108 if (obj.ExpiredTime DateTime.MinValue || DateTime.Now.Subtract(obj.ExpiredTime).TotalSeconds 0)
109 {
110 CacheEntryDictionary.Remove(key);
111 return value;
112 }
113 return (T)Convert.ChangeType(obj.Value, typeof(T));
114 }
115 }
116
117 public static void Remove(string key)
118 {
119 if (string.IsNullOrEmpty(key))
120 throw new ArgumentNullException(nameof(key));
121 try
122 {
123 lock (objLock)
124 {
125 var exist CacheEntryDictionary.ContainsKey(key);
126 if (!exist) return;
127 CacheEntryDictionary.Remove(key);
128 if (FileCacheEntryDictionary.ContainsKey(key))
129 FileCacheEntryDictionary.Remove(key);
130 }
131 }
132 catch (Exception e)
133 {
134 throw e;
135 }
136 }
137
138 public static void Clear()
139 {
140 try
141 {
142 lock (objLock)
143 {
144 CacheEntryDictionary.Clear();
145 FileCacheEntryDictionary.Clear();
146 LastRestoreCachTime DateTime.Now;
147 }
148 }
149 catch (Exception e)
150 {
151 throw e;
152 }
153 }
154
155 public static int Count CacheEntryDictionary?.Count ?? 0;
156
157 private static void RestoreCache()
158 {
159 while (true)
160 {
161 if (CacheEntryDictionary.Keys.Count 1) return;
162 try
163 {
164 bool isEnter false;
165 Monitor.TryEnter(CacheEntryDictionary, 1000, ref isEnter);
166 if (isEnter)
167 {
168 if (CacheEntryDictionary.Count RestoreCacheCount DateTime.Now.Subtract(LastRestoreCachTime).TotalMinutes 1)
169 {
170 var keys CacheEntryDictionary.Where(m m.Value.ExpiredTime DateTime.Now).Select(m m.Key).ToList();
171 foreach (var key in keys)
172 {
173 CacheEntryDictionary.Remove(key);
174 }
175 LastRestoreCachTime DateTime.Now;
176 }
177 }
178 }
179 finally
180 {
181 Monitor.Exit(CacheEntryDictionary);
182 }
183 184 Thread.Sleep(1000 * 6);
185 }
186 }
187
188 private static void ReFreshFileCache()
189 {
190 while (true)
191 {
192 if (FileCacheEntryDictionary.Keys.Count 1) return;
193 try
194 {
195 bool isEnter false;
196 Monitor.TryEnter(FileCacheEntryDictionary, 100, ref isEnter);
197 if (isEnter FileCacheEntryDictionary.Keys.Count 0)
198 {
199 var keys FileCacheEntryDictionary.Keys.ToList();
200 foreach (var key in keys)
201 {
202 var value FileCacheEntryDictionary[key];
203 if (value.ExpiredTime DateTime.Now)
204 {
205 FileCacheEntryDictionary.Remove(key);
206 continue;
207 }
208 var fileCacheOption value.Value as FileCacheOption;
209 if (fileCacheOption null)
210 {
211 FileCacheEntryDictionary.Remove(key);
212 continue;
213 }
214 if (!File.Exists(fileCacheOption.FilePath))
215 {
216 FileCacheEntryDictionary.Remove(key);
217 CacheEntryDictionary.Remove(key);
218 continue;
219 }
220 FileInfo fileInfo new FileInfo(fileCacheOption.FilePath);
221 if (fileInfo.Length ! fileCacheOption.FileSize || fileInfo.LastWriteTime ! fileCacheOption.LastWriteTime)
222 {
223 fileCacheOption.LastWriteTime fileInfo.LastWriteTime;
224 fileCacheOption.FileSize fileInfo.Length;
225 FileCacheEntryDictionary[key] new MyCacheEntity { Value fileCacheOption, ExpiredTime value.ExpiredTime };
226 using (var stream new StreamReader(fileCacheOption.FilePath, fileCacheOption.Encoding))
227 {
228 Set(key, stream.ReadToEnd(), (int)value.ExpiredTime.Subtract(DateTime.Now).TotalSeconds);
229 }
230 }
231 }
232 }
233 }
234 finally
235 {
236 Monitor.Exit(FileCacheEntryDictionary);
237 }
238
239 Thread.Sleep(100);
240 }
241 }
242 }
243 public class MyCacheEntity
244 {
245 public object Value { get; set; }
246 public DateTime ExpiredTime { get; set; }
247 }
248
249 public class FileCacheOption
250 {
251 public string FilePath { get; set; }
252 public long FileSize { get; set; }
253 public DateTime LastWriteTime { get; set; }
254 public Encoding Encoding { get; set; }
255 } 其实上边的文件监控 可以用 FileSystemWatcher 来做文件监控。只是我做测试的时候在触发多个事件读取文件内容时会报文件被占用然后就是在centos 下编辑文件后保存时会同时触发 Created、Changed 两个事件在windows 下不存在这种情况可能是我的方法设置有问题吧。 转载于:https://www.cnblogs.com/flyfishing/articles/Global_CacheHelper.html