最近在看限流相关的技术,看到几种主流的实现限流功能的思想,但刚开始看的时候对令牌桶,漏桶和滑动窗口搞懵逼了,感觉它们的思想好像都是一样的,但为什么又叫不同的名字呢?看别人的代码又看不进去,那么就根据它们的思想自己实现一遍吧
不废话,直接上代码:
public class RealSlidingWindows {
private Long window;
private Long totalPassCount;
private Integer unitWindowCount;
private ConcurrentLinkedDeque<UnitWindows> linkedDeque;
private Long unitWindow;
private AtomicLong windowPassedCount;
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
AtomicLong passCount = new AtomicLong(0);
AtomicLong refuseCount = new AtomicLong(0);
RealSlidingWindows rsw = new RealSlidingWindows(100000L, 100L, 10);
ExecutorService executorService = Executors.newFixedThreadPool(100);
for(int i=0;i<100_000;++i){
Runnable r = () -> {
if(rsw.isPass()){
passCount.incrementAndGet();
}else{
refuseCount.incrementAndGet();
}
};
executorService.execute(r);
}
try {
Thread.sleep(10_000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("耗时:"+(System.currentTimeMillis() - startTime)
+ " passed: "+passCount.get() +" refused: "+refuseCount.get());
executorService.shutdown();
}
public RealSlidingWindows(Long window, Long totalPassCount, Integer unitWindowCount){
this.window = window;
this.totalPassCount = totalPassCount;
this.unitWindowCount = unitWindowCount;
this.linkedDeque = new ConcurrentLinkedDeque();
this.unitWindow = window / unitWindowCount;
this.windowPassedCount = new AtomicLong(0);
}
public boolean isPass(){
long now = System.currentTimeMillis();
UnitWindows unitWindows = new UnitWindows(now);
if(!linkedDeque.isEmpty()){
UnitWindows first = linkedDeque.peekFirst();
if(now - first.getStart() < unitWindow){
unitWindows = first;
}else{
windowPassedCount.addAndGet(-linkedDeque.peekLast().count.get());
linkedDeque.removeLast();
linkedDeque.addFirst(unitWindows);
}
} else {
linkedDeque.addFirst(unitWindows);
}
if(windowPassedCount.incrementAndGet() <= totalPassCount){
unitWindows.count.incrementAndGet();
return true;
}
return false;
}
public static class UnitWindows {
public UnitWindows(Long start){
this.start = start;
this.count = new AtomicLong(0);
}
private Long start;
private AtomicLong count;
public Long getStart() {
return start;
}
public void setStart(Long start) {
this.start = start;
}
public Long getCount() {
return count.get();
}
public void increment(){
count.incrementAndGet();
}
}
}