using System; using System.Threading; namespace TokenBucketLib { /// 令牌桶 public class TokenBucket : IDisposable { #region 公开属性 /// /// 令牌投入速率 /// public int IR { get; set; } private int _BS; /// /// 令牌上限 /// public int BS { get { return _BS; } set { _BS = value; if (CurCount > value) { CurCount = value; } } } /// /// 令牌桶是否在运行 /// public bool Runing { get; set; } /// /// 当前剩余令牌数 /// public int CurCount { get; private set; } #endregion #region 私有字段 /// /// 添加令牌的计时器 /// private Timer timer; /// /// 共享锁 /// protected static readonly object lockkey = new object(); #endregion #region 事件 /// /// 添加令牌完成事件 /// public event Action Put; #endregion #region 构造 /// /// 默认构造,速率100,上限1000 /// public TokenBucket() : this(100, 1000, 1000) { } /// /// 通过指定速率和上限构造令牌桶 /// /// 投入速率 /// 令牌上限 /// 初始令牌数量 public TokenBucket(int ir, int bs, int ip) { IR = ir; BS = bs; CurCount = ip; Runing = false; } #endregion #region 公开方法 /// /// 令牌桶开始工作 /// public virtual void Start() { try { timer = new Timer(PutToken, null, 1000, 1000); Runing = true; } catch (Exception ex) { Runing = false; throw new Exception("TokenBucket start err!", ex); } } /// /// 令牌桶停止工作 /// public virtual void Stop() { if (timer != null) { timer.Dispose(); timer = null; } Runing = false; } /// /// 设置令牌桶满令牌 /// public void SetFullPass() { CurCount = BS; } /// /// 清空令牌桶 /// public void ClearPass() { CurCount = 0; } /// /// 获得一块令牌 /// /// public virtual TokenBucketPass GetToken() { TokenBucketPass tbr = new TokenBucketPass(); if (!Runing) { tbr.State = TokenBucketPassEnum.TokenBucketNotRun; } else { lock (lockkey) { //Console.WriteLine("s"); //Console.WriteLine(CurCount); if (CurCount <= 0) { tbr.State = TokenBucketPassEnum.unpassed; } else { CurCount--; tbr.State = TokenBucketPassEnum.passed; } //Console.WriteLine("e"); } } return tbr; } #endregion #region 私有方法 /// /// 向令牌桶添加令牌 /// /// protected void PutToken(object obj) { if (BS == CurCount) return; lock (lockkey) { CurCount += IR; if (CurCount > BS) { CurCount = BS; } } if (Put != null) Put(this); } #endregion #region IDisposable 成员 private bool IsDisposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!IsDisposed) { //释放托管资源 if (disposing) { if (timer != null) { timer.Dispose(); timer = null; } } //释放非托管资源 } IsDisposed = true; } ~TokenBucket() { Dispose(false); } #endregion } }