缓存技术是一大门槛,怎么构造缓存才是奇思妙解。我是这样认为的,因为一提及缓存,相信大家都能说出个一二的。实际操作是另外一回事的。我分享下我们业务可能会用到的场景。
目的就是从缓存中依次或者排队拿出数据,进而解决并发问题。缓存的学习和应用有一段时间了,推荐这个大佬的讲解https://www.cnblogs.com/wuhuacong/p/3526335.html
我的代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Runtime.Caching; 8 using System.Text; 9 using System.Threading.Tasks; 10 using System.Windows.Forms; 11 12 namespace Test_缓存 13 { 14 public partial class Form1 : Form 15 { 16 public Form1() 17 { 18 InitializeComponent(); 19 } 20 21 List<Emtity> lst = new List<Emtity>(); 22 23 private void button1_Click(object sender, EventArgs e) 24 { 25 26 //for (int i = 0; i < 10; i++) 27 //{ 28 //Emtity mod=new Emtity(); 29 //string str = UHastable<string>.Instance; 30 //mod.Id = i+1; 31 //mod.Name = str; 32 //lst.Add(mod); 33 //} 34 35 //Emtity mod = UHastable<Emtity>.Instance; 36 //lst.Add(mod); 37 38 lst = UHastable<List<Emtity>>.InstanceList; 39 40 } 41 42 private void button2_Click(object sender, EventArgs e) 43 { 44 dataGridView1.DataSource = lst; 45 } 46 47 private void button3_Click(object sender, EventArgs e) 48 { 49 GetUserFullName("2"); 50 } 51 52 /// <summary> 53 /// 根据用户的ID,获取用户的全名,并放到缓存里面 54 /// </summary> 55 /// <param name="userId">用户的ID</param> 56 /// <returns></returns> 57 public string GetUserFullName(string userId) 58 { 59 string key = "Security_UserFullName" + userId; 60 List<Emtity> lst_s = new List<Emtity>(); 61 Emtity mod = new Emtity(); 62 mod.Name = "333"; 63 lst_s.Add(mod); 64 65 string fullName = MemoryCacheHelper.GetCacheItem<string>(key, 66 delegate() { return lst_s[0].Name; }, 67 new TimeSpan(0, 30, 0)); //30分钟过期 68 return fullName; 69 } 70 71 public List<Emtity> GetUsernName() 72 { 73 List<Emtity> lst_uuu = new List<Emtity>(); 74 string key = "Security_UserFullName22"; 75 Emtity mod = new Emtity(); 76 mod.Name = "333"; 77 lst_uuu.Add(mod); 78 MemoryCacheHelper.GetCacheItem<List<Emtity>>(key, 79 delegate() { return lst_uuu; }, 80 new TimeSpan(0, 30, 0)); //30分钟过期 81 return lst_uuu; 82 } 83 string[] str=new string[10]; 84 private int index = 0; 85 private void button4_Click(object sender, EventArgs e) 86 { 87 if (index >= 10) 88 { 89 MessageBox.Show("NO:"+ index.ToString()); 90 return; 91 } 92 for (int i = 0; i < str.Length; i++) 93 { 94 str[i] = "a" + i.ToString(); 95 } 96 List<Emtity> lst_uuu = MemoryCacheHelper.GetCacheItem<List<Emtity>>(str[index], 97 delegate() 98 { 99 List<Emtity> lst_222 = new List<Emtity>(); 100 101 Emtity mod = new Emtity(); 102 mod.Id = index; 103 mod.Name = "333"; 104 lst_222.Add(mod); 105 return lst_222; 106 }, 107 new TimeSpan(0, 30, 0)); //30分钟过期 108 index++; 109 } 110 111 private int count = 0; 112 private void button5_Click(object sender, EventArgs e) 113 { 114 count++; 115 index--; 116 117 var s = MemoryCache.Default[str[index]]; 118 //假设业务需求是取出数据后就移除该数据 则 119 MemoryCache.Default.Remove(str[index]); 120 //让index=10 验证数据是否真正从缓存中移除了 121 if (index == 0) index = 10; 122 123 124 125 if (count >= 10 && count < 20) 126 { 127 //开始验证缓存中的数据是否为空 128 if (s == null) MessageBox.Show("OK,该缓存地址为空。str["+ index + "]"); 129 } 130 //假设所有缓存地址都为空了,这时可以释放该缓存地址了,也可以保留 131 if (count >= 20) 132 { 133 MemoryCache.Default.Dispose(); 134 MessageBox.Show("OK,释放由 System.Runtime.Caching.MemoryCache 类的当前实例占用的所有资源。"); 135 return; 136 } 137 //假设要释放index=8时的缓存地址,然后验证下index<8的缓存地址释放有数据 138 if (index <= 8) 139 { 140 MemoryCache.Default.Dispose(); 141 var s2= (List<Emtity>) MemoryCache.Default[str[index - 1]]; 142 string str55 = 143 string.Format("OK,释放了缓存地址的值str[{0}],下一个值:str[{1}]={2}", index, index - 1, 144 s2 != null ? s2[0].Id.ToString() : "null"); 145 MessageBox.Show(str55); 146 } 147 } 148 } 149 150 public class Emtity 151 { 152 public int Id { get; set; } 153 154 public string Name { get; set; } 155 } 156 157 }
其他类:
MemoryCacheHelper:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Caching; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace Test_缓存 9 { 10 public class MemoryCacheHelper 11 { 12 private static readonly Object _locker=new object(); 13 14 public static T GetCacheItem<T>(String key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null) 15 { 16 if (String.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key"); 17 if (cachePopulate == null) throw new ArgumentNullException("cachePopulate"); 18 if (slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided"); 19 //引用 System.Runtime.Caching https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.caching.memorycache?redirectedfrom=MSDN&view=netframework-4.8 20 if (MemoryCache.Default[key] == null) 21 { 22 lock (_locker) 23 { 24 if (MemoryCache.Default[key] == null) 25 { 26 var item = new CacheItem(key, cachePopulate()); 27 var policy = CreatePolicy(slidingExpiration, absoluteExpiration); 28 29 MemoryCache.Default.Add(item, policy); 30 } 31 } 32 } 33 34 return (T)MemoryCache.Default[key]; 35 } 36 37 private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration) 38 { 39 var policy = new CacheItemPolicy(); 40 41 if (absoluteExpiration.HasValue) 42 { 43 policy.AbsoluteExpiration = absoluteExpiration.Value; 44 } 45 else if (slidingExpiration.HasValue) 46 { 47 policy.SlidingExpiration = slidingExpiration.Value; 48 } 49 50 policy.Priority = CacheItemPriority.Default; 51 52 return policy; 53 } 54 } 55 }
Reflect:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading; 5 using System.Windows.Forms; 6 7 namespace Test_缓存 8 { 9 public class Reflect<T> where T : class 10 { 11 public static T Create() 12 { 13 try 14 { 15 Random rd=new Random(); 16 Thread.Sleep(10); 17 //T t = (T)(object)Convert.ToString(rd.Next(0, 9)); 18 Emtity et =new Emtity(); 19 et.Id = 1; 20 et.Name = "LiuL"; 21 return (T)(object)et; 22 } 23 catch (Exception e) 24 { 25 MessageBox.Show(e.ToString()); 26 return null; 27 } 28 29 30 } 31 32 public static T Create(int index) 33 { 34 try 35 { 36 Random rd = new Random(); 37 Thread.Sleep(10); 38 //T t = (T)(object)Convert.ToString(rd.Next(0, 9)); 39 List<Emtity> lst=new List<Emtity>(); 40 for (int i = 0; i < index; i++) 41 { 42 Emtity et = new Emtity(); 43 et.Id = i+1; 44 et.Name = "LiuL"+ Convert.ToString(rd.Next(0, 9)); 45 lst.Add(et); 46 } 47 return (T)(object)lst; 48 } 49 catch (Exception e) 50 { 51 MessageBox.Show(e.ToString()); 52 return null; 53 } 54 55 56 } 57 } 58 59 }
UHastable:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 using System.Windows.Forms; 8 9 namespace Test_缓存 10 { 11 public class UHastable<T> where T: class 12 { 13 private static Hashtable objCache=new Hashtable(); 14 private static object syncRoot = new Object(); 15 16 private static int _Id; 17 public static int Id { get; set; } 18 public static T Instance 19 { 20 get 21 { 22 //string CacheKey = typeof(T).FullName; 23 /*T bll= (T)objCache[CacheKey];*/ //从缓存读取 24 T bll = (T)objCache[_Id]; 25 if (bll == null) 26 { 27 lock (syncRoot) 28 { 29 if (bll == null) 30 { 31 bll = Reflect<T>.Create();//反射创建,并缓存 32 objCache.Add(_Id, bll); 33 } 34 } 35 } 36 37 _Id++; 38 return bll; 39 } 40 41 } 42 43 public static T InstanceList 44 { 45 get 46 { 47 T bll = (T)objCache[_Id]; 48 if (bll == null) 49 { 50 lock (syncRoot) 51 { 52 if (bll == null) 53 { 54 bll = Reflect<T>.Create(10);//反射创建,并缓存 55 objCache.Add(_Id, bll); 56 } 57 } 58 } 59 60 _Id++; 61 return bll; 62 } 63 64 } 65 } 66 67 68 }
测试数据都是模拟数据。