using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; namespace TokenBucketLib { /// /// 队列令牌桶 /// 资源请求首先到达令牌桶,如果获得令牌马上返回,如果失败将进入等待队列,等待获得令牌后返回,或者令牌桶满后获取失败并丢弃。 /// public class QueueTokenBucket : TokenBucket { /// /// 最大缓冲对列数。-1为不限长度。 /// public int QueueMaxLenth { get; set; } private Queue queue; private readonly static object objlock = new object(); /// /// 构造一个带缓冲队列的令牌桶 /// public QueueTokenBucket() : this(-1) { } /// /// 通过提供最大缓冲队列数构造缓冲队列令牌桶 /// /// 缓冲区大小。-1为不限制大小。 public QueueTokenBucket(int queueMaxLenth) { QueueMaxLenth = queueMaxLenth; queue = new Queue(); base.Put += new Action(QueueTokenBuket_Put); } private void QueueTokenBuket_Put(TokenBucket obj) { if (queue.Count > 0) { lock (objlock) { var c = queue.Count; for (int i = 0; i < c; i++) { var r = base.GetToken(); if (r.State == TokenBucketPassEnum.passed) { TokenBucketPass result = queue.Dequeue(); result.State = TokenBucketPassEnum.passed; if (GetTokenEnd != null) GetTokenEnd(this, new TokenBucketEventArgs(result)); } else { break; } } } } } /// /// /// public event Action GetTokenEnd; /// /// 开始异步获取令牌 /// /// 异步传入的对象,这个对象会随TokenBucketPass.Requester传出。 public void GetTokenAsyn(object requester) { var result = new TokenBucketPass(); result.Requester = requester; var r = base.GetToken(); if (r.State == TokenBucketPassEnum.passed) { result.State = r.State; if (GetTokenEnd != null) GetTokenEnd(this, new TokenBucketEventArgs(result)); } else { if (QueueMaxLenth != -1 && QueueMaxLenth < queue.Count) { result.State = TokenBucketPassEnum.losted; GetTokenEnd(this, new TokenBucketEventArgs(result)); } else { queue.Enqueue(result); } } } #region IDisposable 成员 protected override void Dispose(bool disposing) { if (disposing) { queue.Clear(); } base.Dispose(disposing); } #endregion } }