|
@@ -0,0 +1,200 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Threading;
|
|
|
+using LJLib.D;
|
|
|
+
|
|
|
+namespace LJLib
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 缓存,超时自动清除,线程安全
|
|
|
+ /// </summary>
|
|
|
+ public sealed class LJCache<TKey, TValue> : Dictionary<TKey, TValue>
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 自动延长分钟数
|
|
|
+ /// </summary>
|
|
|
+ public double DefaultAddMinutes
|
|
|
+ {
|
|
|
+ get { return _defaultAddMinutes;}
|
|
|
+ set { _defaultAddMinutes = value; }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 添加键值对,
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key"></param>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ /// <param name="minutes">超时分钟数</param>
|
|
|
+ public void Add(TKey key, TValue value, double minutes)
|
|
|
+ {
|
|
|
+ var deadline = DateTime.Now.AddMinutes(minutes);
|
|
|
+ Add(key, value, deadline);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 添加永久对象或者按默认时间添加
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key"></param>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ public new void Add(TKey key, TValue value)
|
|
|
+ {
|
|
|
+ Add(key, value, _defaultAddMinutes);
|
|
|
+ }
|
|
|
+
|
|
|
+ public new TValue this[TKey key]
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ lock (syncRoot)
|
|
|
+ {
|
|
|
+ SetDeadLine(key, DateTime.Now.AddMinutes(DefaultAddMinutes));
|
|
|
+ return base[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ lock (syncRoot)
|
|
|
+ {
|
|
|
+ SetDeadLine(key, DateTime.Now.AddMinutes(DefaultAddMinutes));
|
|
|
+ base[key] = value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public new bool ContainsKey(TKey key)
|
|
|
+ {
|
|
|
+ lock (syncRoot)
|
|
|
+ {
|
|
|
+ var rslt = base.ContainsKey(key);
|
|
|
+ if (rslt)
|
|
|
+ {
|
|
|
+ SetDeadLine(key, DateTime.Now.AddMinutes(DefaultAddMinutes));
|
|
|
+ }
|
|
|
+ return rslt;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #region 稀有成员实现逻辑
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 添加键值对,设置超时时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key"></param>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ /// <param name="deadline">超时时间</param>
|
|
|
+ private void Add(TKey key, TValue value, DateTime deadline)
|
|
|
+ {
|
|
|
+ lock (syncRoot)
|
|
|
+ {
|
|
|
+ base[key] = value;
|
|
|
+ SetDeadLine(key, deadline);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 手动设置超时时间
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="key"></param>
|
|
|
+ /// <param name="deadline"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private void SetDeadLine(TKey key, DateTime deadline)
|
|
|
+ {
|
|
|
+ lock (syncRoot)
|
|
|
+ {
|
|
|
+ deadline = deadline.AddMilliseconds(-deadline.Millisecond);
|
|
|
+
|
|
|
+ if (_deadlines == null)
|
|
|
+ {
|
|
|
+ _deadlines = new Dictionary<TKey, DateTime>();
|
|
|
+ _ix_keys = new SortedList<DateTime, HashSet<TKey>>();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_deadlines.ContainsKey(key))
|
|
|
+ {
|
|
|
+ var olddt = _deadlines[key];
|
|
|
+ _ix_keys[olddt].Remove(key);
|
|
|
+ if (_ix_keys[olddt].Count == 0)
|
|
|
+ {
|
|
|
+ _ix_keys.Remove(olddt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ _deadlines[key] = deadline;
|
|
|
+ if (!_ix_keys.ContainsKey(deadline))
|
|
|
+ {
|
|
|
+ _ix_keys[deadline] = new HashSet<TKey>();
|
|
|
+ }
|
|
|
+ if (!_ix_keys[deadline].Contains(key))
|
|
|
+ {
|
|
|
+ _ix_keys[deadline].Add(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_timer == null)
|
|
|
+ {
|
|
|
+ _timer = new Timer((state) =>
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //DebugHelper.GetTotalMemory("LJCache.Remove.开始");
|
|
|
+ lock (syncRoot)
|
|
|
+ {
|
|
|
+ var dtNow = DateTime.Now;
|
|
|
+ List<DateTime> dts = new List<DateTime>();
|
|
|
+ for (int i = 0; _ix_keys != null && i < _ix_keys.Keys.Count && _ix_keys.Keys[i] <= dtNow; i++)
|
|
|
+ {
|
|
|
+ dts.Add(_ix_keys.Keys[i]);
|
|
|
+ foreach (var oldkey in _ix_keys.Values[i])
|
|
|
+ {
|
|
|
+ _deadlines.Remove(oldkey);
|
|
|
+ base.Remove(oldkey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ foreach (var dt in dts)
|
|
|
+ {
|
|
|
+ _ix_keys.Remove(dt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //DebugHelper.GetTotalMemory("LJCache.Remove.结束");
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Trace.Write(ex);
|
|
|
+ }
|
|
|
+ }, null, 1000, 1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 线路同步对象
|
|
|
+ /// </summary>
|
|
|
+ private object syncRoot = new object();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 缓存清除定时器
|
|
|
+ /// </summary>
|
|
|
+ private Timer _timer;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 各键值对的销毁时间
|
|
|
+ /// </summary>
|
|
|
+ private Dictionary<TKey, DateTime> _deadlines;
|
|
|
+ /// <summary>
|
|
|
+ /// 按时间顺序过期
|
|
|
+ /// </summary>
|
|
|
+ private SortedList<DateTime, HashSet<TKey>> _ix_keys;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 自动延长分钟数
|
|
|
+ /// </summary>
|
|
|
+ private double _defaultAddMinutes = 5;
|
|
|
+
|
|
|
+ public LJCache(IEqualityComparer<TKey> comparer) : base(comparer) { }
|
|
|
+
|
|
|
+ public LJCache() : base() { }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|