时间滑动窗口限制请求次数

一、时间窗口固定

使用map存储,key为唯一值,value为一个实体,存着开始时间和次数,取出来判断是否为空,如果为空就新建一个对象进去并且如果不为空并且当前时间-取出来的时间>最大时间限制值,重新赋值value,value=当前时间,次数1,返回可以请求,如果上述条件不满足,则判断次数是否>=最大限制,如果大于就返回不让请求,如果小于,则次数加1返回可以请求。

缺点:时间快结束和时间开始的时候会在xxx区间的时候大于某段时间内最请求 所以看下面时间滑动窗口解决

import java.util.HashMap;
import java.util.Map;

public class RequestLimiter {
    private static final int MAX_REQUESTS = 5; // 最大请求次数
    private static final long MAX_TIME_WINDOW = 60 * 1000; // 最大时间窗口,单位:毫秒

    private Map<String, RequestEntity> requestMap = new HashMap<>();

    public boolean canMakeRequest(String key) {
        long currentTime = System.currentTimeMillis();
        RequestEntity entity = requestMap.get(key);

        if (entity == null) {
            // 如果唯一标识符不存在于Map中,创建一个新的实体对象
            entity = new RequestEntity(currentTime, 1);
            requestMap.put(key, entity);
            return true;
        } else {
            // 如果唯一标识符存在
            long elapsedTime = currentTime - entity.getStartTime();

            if (elapsedTime > MAX_TIME_WINDOW) {
                // 如果时间窗口过期,重新设置实体对象的值
                entity.setStartTime(currentTime);
                entity.setCount(1);
                return true;
            } else if (entity.getCount() < MAX_REQUESTS) {
                // 如果在时间窗口内,但请求次数未达到限制,增加次数
                entity.setCount(entity.getCount() + 1);
                return true;
            } else {
                // 如果次数已达到限制,不允许请求
                return false;
            }
        }
    }

    public static void main(String[] args) {
        RequestLimiter requestLimiter = new RequestLimiter();

        String key = "user123";

        for (int i = 0; i < 10; i++) {
            if (requestLimiter.canMakeRequest(key)) {
                System.out.println("Request allowed");
            } else {
                System.out.println("Request not allowed");
            }
        }
    }
}

class RequestEntity {
    private long startTime;
    private int count;

    public RequestEntity(long startTime, int count) {
        this.startTime = startTime;
        this.count = count;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}



二、时间滑动窗口

public class TimeSlidingWindow {
    private Deque<Long> window;  // 存储时间戳的双端队列
    private int windowSize;      // 窗口大小
    private long windowDuration; // 窗口持续时间(毫秒)

    public TimeSlidingWindow(int windowSize, long windowDuration) {
        this.window = new ArrayDeque<>();
        this.windowSize = windowSize;
        this.windowDuration = windowDuration;
    }

    public Boolean addTimestamp(long timestamp) {
        // 移除超出窗口持续时间的时间戳
        long threshold = timestamp - windowDuration;
        //如果不为空&&拿出第一比较  超出窗口持续时间的时间戳
        while (!window.isEmpty() && window.peekFirst() < threshold) {
        	//移除
            window.pollFirst();
        }

		if(window.size() >= windowSize) {
		 return false;
		}
        // 添加新的时间戳到窗口末尾
        window.offerLast(timestamp);
        return true;
    }
   }






你可能感兴趣的:(算法,java,开发语言)