基于linkedqueue 的滑动时间窗口限流
package com.heshen.algorithm.leakybucket;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.IntStream;
public class TimeWindow {
private ConcurrentLinkedQueue<Long> queue = new ConcurrentLinkedQueue<Long>();
private int seconds;
private int max;
public TimeWindow(int max, int timeWindowOfSeconds){
this.seconds = timeWindowOfSeconds;
this.max = max;
new Thread(new Runnable(){
@Override
public void run() {
for(;;){
clean();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}).start();
}
/**
* 获取令牌,并且添加时间
*/
public void take(){
long start = System.currentTimeMillis();
try {
int size = sizeOfValid();
if (size > max - 1) {
System.err.println(" full queue:size:" + queue.size() + ",max:" + max + ",queue:" + printQueue());
throw new IllegalStateException("full");
}
synchronized (queue) {
if (sizeOfValid() > max - 1) {
System.err.println(" full queue: in synchronized,size:" + queue.size() + ",max:" + max + ",queue:" + printQueue());
throw new IllegalStateException("full");
}
this.queue.offer(System.currentTimeMillis());
}
System.out.println(" queue: d,size:" + queue.size() + ",max:" + max + ",queue:" + printQueue());
}finally {
System.out.println("cost:"+(System.currentTimeMillis() - start) + " ms");
}
}
private String printQueue(){
Iterator<Long> it = queue.iterator();
StringBuilder sb = new StringBuilder();
while (it.hasNext()){
Long t = it.next();
sb.append(" ").append(t);
}
return sb.toString();
}
public int sizeOfValid(){
Iterator<Long> it = queue.iterator();
Long ms = System.currentTimeMillis() - seconds * 1000;
int count = 0;
while (it.hasNext()){
long t = it.next();
if(t > ms){
count++;
}
}
return count;
}
/**
* 清理
*/
public void clean(){
Long c = System.currentTimeMillis() - seconds * 1000;
Long tl = null;
System.out.println("peek: "+queue.peek() +"c:"+ c);
while((tl = queue.peek()) != null && tl < c){
System.out.println("peek: t:"+ tl);
queue.poll();
}
}
public static void main(String[] args){
final TimeWindow timeWindow = new TimeWindow(200, 2);
IntStream.range(0, 100).forEach((i)->{
new Thread(() -> {
for(;;){
System.out.println("before take i:"+i);
try {
Thread.sleep(new Random().nextInt(20)* 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
try{
timeWindow.take();
System.out.println("some option, i:"+i);
}catch (Exception e){
System.err.println(" take i:"+i +", encounter error:"+ e.getMessage());
try {
Thread.sleep(10L);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
continue;
}
System.out.println("after take i:"+i);
}
}).start();
});
}
}
需求在某个滑动的时间窗口内,限定访问次数