
下面使用ConcurrentHashMapConcurrentLinkedDeque实现一个滑动窗口限流器限制在10 秒内最多 N 次请求例如 5 次。这种方案只依赖本地内存适合单机限流场景。实现原理为每个用户或 IP维护一个双端队列存储每次请求的时间戳毫秒。每次请求时先清理队列中超过 10 秒的旧时间戳再判断队列大小是否小于阈值若小于则添加当前时间戳返回允许否则返回限流。使用ConcurrentHashMap保证对用户 Key 的线程安全使用synchronized对每个队列做同步避免并发修改。代码实现javaimport java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.TimeUnit; /** * 基于 Map 的滑动窗口限流器10秒限频 */ public class LocalSlidingWindowRateLimiter { // 存储每个用户的请求时间戳队列 private final MapString, ConcurrentLinkedDequeLong userQueueMap new ConcurrentHashMap(); private final int windowSeconds; // 窗口大小秒 private final int maxRequests; // 窗口内最大请求数 public LocalSlidingWindowRateLimiter(int windowSeconds, int maxRequests) { this.windowSeconds windowSeconds; this.maxRequests maxRequests; } /** * 检查是否允许请求 * param key 限流标识如 userId、ip * return true 允许false 被限流 */ public boolean allowRequest(String key) { long now System.currentTimeMillis(); long windowStart now - TimeUnit.SECONDS.toMillis(windowSeconds); // 获取或创建该用户的队列 ConcurrentLinkedDequeLong deque userQueueMap.computeIfAbsent(key, k - new ConcurrentLinkedDeque()); // 对队列加锁保证清理和添加的原子性 synchronized (deque) { // 1. 清理过期记录窗口外的旧时间戳 while (!deque.isEmpty() deque.peekFirst() windowStart) { deque.pollFirst(); } // 2. 判断是否超过阈值 if (deque.size() maxRequests) { // 允许请求记录当前时间戳 deque.addLast(now); return true; } else { return false; } } } // 可选定期清理无数据的用户 Key避免内存泄漏可以用 ScheduledExecutorService 定时清理 public void cleanEmptyKeys() { userQueueMap.entrySet().removeIf(entry - entry.getValue().isEmpty()); } }使用示例javapublic class Main { public static void main(String[] args) throws InterruptedException { // 限流规则10秒内最多5次请求 LocalSlidingWindowRateLimiter limiter new LocalSlidingWindowRateLimiter(10, 5); String userId user_123; for (int i 0; i 10; i) { boolean allowed limiter.allowRequest(userId); System.out.println(请求 (i 1) (allowed ? 通过 : 限流)); Thread.sleep(1000); // 模拟间隔 1 秒 } } }输出示例第 6 次请求被限流因为 10 秒内已有 5 次text请求 1通过 请求 2通过 请求 3通过 请求 4通过 请求 5通过 请求 6限流 请求 7限流 ...注意事项内存清理长期不活动的用户 Key 会残留队列对象建议定时调用cleanEmptyKeys()清理。并发安全每个队列使用synchronized锁保证原子操作锁粒度小性能较高。时间精度使用毫秒级时间戳滑动窗口边界判断精确。适用场景单机应用、对分布式一致性要求不高的限流场景。