使用ConcurrentDictionary实现轻量缓存
2015-07-30 15:43 Nicolas.wang 阅读(1074) 评论(0) 编辑 收藏 举报项目中需要用到一个轻量缓存,存储重复使用的数据。
在设计中需要考虑:
1.做成通用组件,为未来其他模块方法操作结果做准备。
2.缓存模块需要接口化,为未来替换使用外部缓存做准备。
3.使用默认缓存过期时间,单个Key的过期时间可以自由配置。
使用ConcurrentDictionary来作为我们的缓存容器,并能保证线程安全。
1 public interface IDataCache 2 { 3 TimeSpan Ttl 4 { 5 get; 6 } 7 8 void Set(string key, object value); 9 10 void Set(string key, object value, TimeSpan ttl); 11 12 object Get(string key); 13 14 void PurgeExpiredEntries(); 15 }
1 /// <summary> 2 /// An implementation of <see cref="IDataCache"/> which uses a dictionary to cache values in memory. 3 /// </summary> 4 public class InMemDataCache:IDataCache 5 { 6 private static readonly TimeSpan DefaultTtl = TimeSpan.FromMinutes(10); 7 8 private readonly TimeSpan _ttl; 9 private readonly ConcurrentDictionary<string, CacheEntry> _cache = new ConcurrentDictionary<string, CacheEntry>(); 10 11 /// <summary> 12 /// Initialize a new instance of <see cref="InMemDataCache"/> using the default TTL. 13 /// </summary> 14 public InMemDataCache() 15 : this(DefaultTtl) 16 { 17 18 } 19 20 /// <summary> 21 /// Initialize a new instance of <see cref="InMemDataCache"/> using a specified TTL. 22 /// </summary> 23 /// <param name="ttl"> 24 /// The time-to-live (TTL) of value saved into the cache. Zero or negative value indicates that values shall never expire. 25 /// </param> 26 public InMemDataCache(TimeSpan ttl) 27 { 28 _ttl = ttl; 29 } 30 31 /// <summary> 32 /// The time-to-live (TTL) of value saved into the cache. 33 /// </summary> 34 public TimeSpan Ttl 35 { 36 get 37 { 38 return _ttl; 39 } 40 } 41 42 /// <summary> 43 /// Save a key-value pair into the cache using the global TTL settings. 44 /// Existed value associated with the specified key shall be overwritten. 45 /// </summary> 46 /// <param name="key"></param> 47 /// <param name="value"></param> 48 public void Set(string key, object value) 49 { 50 Set(key, value, _ttl); 51 } 52 53 /// <summary> 54 /// Save a key-value pair into the cache using the global TTL settings. 55 /// Existed value associated with the specified key shall be overwritten. 56 /// </summary> 57 /// <param name="key"></param> 58 /// <param name="value"></param> 59 /// <param name="ttl"> 60 /// The time-to-live (TTL) of value saved into the cache. Zero or negative value indicates that values shall never expire. 61 /// </param> 62 public void Set(string key, object value, TimeSpan ttl) 63 { 64 var expirationTime = ttl <= TimeSpan.Zero ? DateTime.MinValue : DateTime.Now.Add(ttl); 65 var result = new CacheEntry(value, expirationTime); 66 _cache.AddOrUpdate(key, result, (k, o) => result); 67 } 68 69 public object Get(string key) 70 { 71 CacheEntry entry; 72 if (!_cache.TryGetValue(key, out entry)) 73 { 74 return null; 75 } 76 77 if (entry.ExpirationTime == DateTime.MinValue || DateTime.Now < entry.ExpirationTime) 78 { 79 return entry.Value; 80 } 81 82 CacheEntry old; 83 _cache.TryRemove(key, out old); 84 return null; 85 } 86 87 public void PurgeExpiredEntries() 88 { 89 foreach (var key in _cache.Keys) 90 { 91 Get(key); 92 } 93 } 94 95 private class CacheEntry 96 { 97 public readonly object Value; 98 public readonly DateTime ExpirationTime; 99 100 public CacheEntry(object value, DateTime expirationTime) 101 { 102 // TODO: Complete member initialization 103 Value = value; 104 ExpirationTime = expirationTime; 105 } 106 } 107 }
完整demo路径:https://files.cnblogs.com/files/Nicolas-wang/Examples.Cache.zip