日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于全局缓存的一种简单实现方法

發布時間:2023/12/2 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于全局缓存的一种简单实现方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

緩存,在.Net系統開發中,經常使用到。如果,讓你自己去實現,你會怎么做呢。

開始編碼前思考:

?1、肯定 是要 根據 key 去查詢對應value,so 應該是List<KeyValuePair> 這類集合做緩存載體;

?2、肯定是要全局公用,so 緩存的列表應該唯一;

?3、應該有支持并發的能力,so 實現過程中肯定要加鎖;?

?4、應該可以支持過期,自動 or 手動,so 應該 可以添加過期時間;

好的,基于以上3點,設計的類應該需要是單體(單例)模式,查詢、刪除key時應該lock 緩存載體,可以有定時清除過期緩存項的能力;

1 public static class CacheHelper 2 { 3 private static int RestoreCacheCount = 20000; 4 private static DateTime LastRestoreCachTime; 5 private static Dictionary<string, 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 Dictionary<string, MyCacheEntity>(); 17 LastRestoreCachTime = DateTime.Now; 18 System.Threading.Tasks.Task.Factory.StartNew(() => RestoreCache()); 19 } 20 } 21 } 22 } 23 24 public static void Set<T>(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 else 39 { 40 CacheEntryDictionary[key] = new MyCacheEntity { Value = entity, ExpiredTime = expiredTime }; 41 } 42 } 43 } 44 45 public static T Get<T>(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 try 74 { 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 try 91 { 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 Dictionary<string, MyCacheEntity>(StringComparer.OrdinalIgnoreCase);

你可能會有疑問,為什么不用 線程安全的字典?ConcurrentDictionary 呢?

當然可以將?Dictionary 改為?ConcurrentDictionary 沒有任何問題,只是我想要自己手動實現加減速的過程;ConcurrentDictionary 字典內部也是調用Monitor 進行的加減鎖的過程;

如果想要在緩存中實現 緩存文件,并且文件內容改變同步修改緩存的內容呢?

修改 以上方法 加入

?1、添加緩存文件

?2、刷新緩存文件內容,定時過期、監控文件內容更改等;

相關代碼;

1 public static class CacheHelper 2 { 3 private static int RestoreCacheCount = 20000; 4 private static DateTime LastRestoreCachTime; 5 private static Dictionary<string, MyCacheEntity> CacheEntryDictionary; 6 private static readonly object objLock = new object(); 7 private static Dictionary<string, MyCacheEntity> FileCacheEntryDictionary; 8 9 static CacheHelper() 10 { 11 if (CacheEntryDictionary == null) 12 { 13 lock (objLock) 14 { 15 if (CacheEntryDictionary == null) 16 { 17 CacheEntryDictionary = new Dictionary<string, MyCacheEntity>(StringComparer.OrdinalIgnoreCase); 18 LastRestoreCachTime = DateTime.Now; 19 System.Threading.Tasks.Task.Factory.StartNew(() => RestoreCache()); 20 } 21 if (FileCacheEntryDictionary == null) 22 { 23 FileCacheEntryDictionary = new Dictionary<string, MyCacheEntity>(); 24 System.Threading.Tasks.Task.Factory.StartNew(() => ReFreshFileCache()); 25 } 26 } 27 } 28 } 29 30 public static void Set<T>(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 else 45 { 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 else 66 { 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 MyCacheEntity 74 { 75 Value = value, 76 ExpiredTime = expiredTime 77 }; 78 FileCacheEntryDictionary[key] = new MyCacheEntity 79 { 80 Value = new FileCacheOption 81 { 82 FilePath = filePath, 83 FileSize = fileInfo.Length, 84 LastWriteTime = fileInfo.LastWriteTime, 85 Encoding = encoding 86 }, 87 ExpiredTime = expiredTime 88 }; 89 } 90 } 91 } 92 93 public static T Get<T>(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

總結

以上是生活随笔為你收集整理的关于全局缓存的一种简单实现方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久人人干 | av网子| 久久久无码精品亚洲无少妇 | 国产精品天美传媒沈樵 | 中国黄色免费 | 夜夜夜操操操 | 亚洲在线一区二区三区 | 曰本三级日本三级日本三级 | 天天摸夜夜添狠狠添婷婷 | 国产精品亚洲一区二区三区 | 久伊人网| 三级av网址| 中文字幕免费观看 | 荒野求生21天去码版网站 | 久久av在线 | 狠狠躁夜夜 | 牛牛在线| 蜜臀在线一区二区三区 | 亚洲精品97久久中文字幕 | 综合视频一区 | 奇米影视大全 | 色盈盈影院 | 国产按摩一区二区三区 | 国产美女无遮挡免费视频 | 欧美三日本三级少妇99 | 午夜影院a | 麻豆成人免费视频 | 日韩欧美高清片 | 亚洲精品综合久久 | 丰满少妇一区 | 欧洲影院| 欧美在线播放一区 | 欧美污视频| 九九热re | 精品99久久久久成人网站免费 | www..99热 | 亚洲拍拍视频 | 99精品久久精品一区二区 | 九九热视频在线观看 | 男人网站在线观看 | 国产精品午夜在线观看 | 无码人妻精品中文字幕 | 制服丝袜一区 | 国产免费观看av | 日本伊人色 | 精品人妻aV中文字幕乱码色欲 | 欧美日韩高清在线观看 | 粉色视频免费观看 | 豆花av| 日本伦理一区二区三区 | 日韩亚洲在线观看 | 精品久久久久一区二区 | 国产精品久久久久久妇女6080 | 神马久久影院 | 色批网站 | 国产又粗又猛又爽又黄91精品 | 欧美成人激情视频 | 一级做a爱片久久 | 日本综合久久 | 天天操天天射天天舔 | 女人高潮潮呻吟喷水 | 国产高清在线一区 | 久久人妖 | 国产片天天弄 | 一区二区三区国产精品 | 红桃视频91 | 天天操好逼 | 另类激情视频 | 麻豆传媒在线观看视频 | 毛片成人网 | 成人一区二 | 国内精品在线观看视频 | 精品丝袜一区 | 中文字幕首页 | 日本99热 | 91免费成人| 欧美性猛交ⅹxxx乱大交3 | 国产精品久久久久久久久久久新郎 | 欧美系列在线观看 | 五月婷婷久久久 | 妖精视频在线观看 | 黄色三级在线视频 | 日本一级黄色 | 激情文学综合网 | a资源在线观看 | 国产一级在线观看 | 最近中文字幕av | 国产啊v在线观看 | 久久伊人一区 | 老女人人体欣赏a√s | 亚洲性大片 | 九九久久免费视频 | 亚洲免费三区 | 国产视频精选 | 蜜桃综合网 | 日韩精品一区二区亚洲av性色 | 中文字幕在线观看高清 | 99九九精品视频 | 人妻互换 综合 |