//限流组件,采用数组作为一个环
class LimitService
{
//当前指针的位置
int currentIndex = 0;
//限制的时间的秒数,即:x秒容许多少请求
int limitTimeSencond = 1;
//请求环的容器数组
DateTime?[] requestRing = null;
//容器改变或者移动指针时候的锁
object objLock = new object();
public LimitService(int countPerSecond,int _limitTimeSencond)
{
requestRing = new DateTime?[countPerSecond];
limitTimeSencond= _limitTimeSencond;
}
//程序是否能够继续
public bool IsContinue()
{
lock (objLock)
{
var currentNode = requestRing[currentIndex];
//若是当前节点的值加上设置的秒 超过当前时间,说明超过限制
if (currentNode != null&& currentNode.Value.AddSeconds(limitTimeSencond) >DateTime.Now)
{
returnfalse;
}
//当前节点设置为当前时间
requestRing[currentIndex] = DateTime.Now;
//指针移动一个位置
MoveNextIndex(ref currentIndex);
}
returntrue;
}
//改变每秒能够经过的请求数
public bool ChangeCountPerSecond(int countPerSecond)
{
lock (objLock)
{
requestRing = new DateTime?[countPerSecond];
currentIndex = 0;
}
returntrue;
}
//指针往前移动一个位置
private void MoveNextIndex(ref int currentIndex)
{
if (currentIndex != requestRing.Length - 1)
{
currentIndex = currentIndex + 1;
}
else
{
currentIndex = 0;
}
}
}
复制代码
测试程序以下:
static LimitService l = new LimitService(1000, 1);
static void Main(string[] args)
{
int threadCount = 50;
while (threadCount >= 0)
{
Thread t = new Thread(s =>
{
Limit();
});
t.Start();
threadCount--;
}
Console.Read();
}
static void Limit()
{
int i = 0;
int okCount = 0;
int noCount = 0;
Stopwatch w = new Stopwatch();
w.Start();
while (i < 1000000)
{
var ret = l.IsContinue();
if (ret)
{
okCount++;
}
else
{
noCount++;
}
i++;
}
w.Stop();
Console.WriteLine($"共用{w.ElapsedMilliseconds},容许:{okCount}, 拦截:{noCount}");
}
复制代码