//限流組件,採用數組作爲一個環
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}");
}
複製代碼