C#缓存的一点想法及测试

项目开发中,用到了缓存,其中的一个列表项,可能要多线程处理,就有了下面的想法,具体的问题在代码中有详细说明,见下文。

 

 1         static void Main(string[] args) {
 2 
 3           
 4 
 5             测试缓存的想法();
 6 
 7             Console.WriteLine("测试结束!");
 8             Console.ReadKey();
 9         }
10 
11         /// <summary>
12         /// 静态的缓存,测试缓存是否存放的指针
13         /// </summary>
14         private static MemoryCache memoryCache = MemoryCache.Default;
15 
16         private static void 测试缓存的想法() {
17 
18             Console.WriteLine("创建一个测试的整型列表:");
19 
20             List<int> ints = new List<int>();
21 
22             Console.WriteLine("列表中放入{1,2,3}  3个数字");
23             
24             ints.Add(1);
25             ints.Add(2);
26             ints.Add(3);
27 
28             //缓存的策略,10分钟,测试够用了
29             var policy = new CacheItemPolicy();
30             policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(10);
31 
32             Console.WriteLine("将整型列表放入缓存,缓存10分钟:");
33             memoryCache.Set("key", ints, policy);
34 
35             //不取出更改原有的列表,去除第2个数字
36             Console.WriteLine("更新原有列表的数据,去除第2个数字,缓存不做处理:");
37             ints.Remove(2);
38 
39             Console.WriteLine("从缓存中取出对应的缓存列表,打印缓存列表项");
40 
41             var result = (List<int>)memoryCache.Get("key");
42 
43             result.ForEach(r => { Console.WriteLine(r); });
44 
45             Console.WriteLine("-----------------第一阶段测试完成------------------------");
46             Console.WriteLine("");
47 
48             Console.WriteLine("直接处理缓存列表项,去除第1个数字,并且没有再次保存至缓存的动作:");
49             result.Remove(1);
50 
51             Console.WriteLine("打印缓存中的列表项:");
52             //下面这句有没有,打印的结果是一样的
53             result = (List<int>)memoryCache.Get("key");
54             result.ForEach(r => { Console.WriteLine(r); });
55 
56             Console.WriteLine("");
57             Console.WriteLine("打印原列表项:");
58           
59             ints.ForEach(r => { Console.WriteLine(r); });
60 
61             Console.WriteLine("-----------------第二阶段测试完成------------------------");
62 
63             Console.WriteLine("直接操作原有的列表项,添加一个数字4:");
64             ints.Add(4);
65 
66             Console.WriteLine("不重新取缓存项,打印缓存中的列表项:");
67             //下面这句有没有,打印的结果是一样的
68             result.ForEach(r => { Console.WriteLine(r); });
69 
70             Console.WriteLine("");
71             Console.WriteLine("打印原列表项:");
72 
73             ints.ForEach(r => { Console.WriteLine(r); });
74 
75             Console.WriteLine("-----------------第三阶段测试完成------------------------");
76 
77             /*
78              * 结论:
79              * 
80              * 缓存内部存放的对象的指针,不管是原对象的直接修改,或对缓存项的修改
81              * 只要缓存的指针没有发生变化,对此对象的修改会同步传导到缓存及原对象的指针
82              */
83         }


其实这个测试并没有什么新意,在.Net中关于对象在内存中的存放位置相关的文章中有明确的说明:

对象放在托管堆上,对象本身有个指针指向这个托管堆,(虽然这个指针可能会随着GC的运行发生动态调整,但是我们仍然可以当做指针来理解)

上面测试中的缓存项与原有的列表项,其实指向的是同一块内存,对其中的任何修改,会同时传导到两个对象。理解不了需要看一下.Net的底层的相关知识

结合C语言的指针理解起来其实更容易一些。

 

我想要多线程处理这个缓存列表安全,此时可以换用 ConcurrentBag ,没见过这个对象的同学可以参考MSDN,这是一个多线程操作安全的无序集合。

此时便可以多线程得到这个缓存项(ConcurrentBag)的 对象,做相应的操作即可,问题解决。

 

语言表达能力有限,欢迎批评指正,有砖轻轻拍。

 

posted @ 2015-07-22 19:39  心如止水-杜  阅读(486)  评论(0编辑  收藏  举报
技术文章,欢迎转载,转载请注明出处。 杜鹤飞的技术博客 邮箱地址:dhf327@163.com