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

一、时间窗口固定

使用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;
    }
   }






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张航柯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值