Java项目不使用框架如何实现限流?

简介: Java项目不使用框架如何实现限流?

在Java项目中,如果不使用任何框架来实现限流,可以通过手动编写代码来控制请求的速率。以下是一个简单的示例,展示了如何使用令牌桶算法实现限流:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class RateLimiter {
   
    private final long maxTokens; // 最大令牌数
    private final long refillTokens; // 每次补充的令牌数
    private final long refillPeriod; // 补充令牌的时间间隔(毫秒)
    private long lastRefillTimestamp; // 上次补充令牌的时间戳
    private long currentTokens; // 当前令牌数
    private final LinkedBlockingQueue<Long> tokenBucket; // 存放令牌的队列

    public RateLimiter(long maxTokens, long refillTokens, long refillPeriod) {
   
        this.maxTokens = maxTokens;
        this.refillTokens = refillTokens;
        this.refillPeriod = refillPeriod;
        this.lastRefillTimestamp = System.currentTimeMillis();
        this.currentTokens = maxTokens;
        this.tokenBucket = new LinkedBlockingQueue<>(maxTokens);

        // 初始化令牌桶
        for (int i = 0; i < maxTokens; i++) {
   
            tokenBucket.offer(System.currentTimeMillis());
        }

        // 启动一个定时任务,定期补充令牌
        new Thread(() -> {
   
            while (!Thread.interrupted()) {
   
                try {
   
                    TimeUnit.MILLISECONDS.sleep(refillPeriod);
                    refill();
                } catch (InterruptedException e) {
   
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }

    public boolean tryAcquire() {
   
        long now = System.currentTimeMillis();
        if (now - lastRefillTimestamp >= refillPeriod) {
   
            refill();
        }

        if (tokenBucket.isEmpty()) {
   
            return false; // 没有可用的令牌
        } else {
   
            Long token = tokenBucket.poll();
            if (token != null && token <= now) {
   
                return true; // 令牌有效
            } else {
   
                tokenBucket.offer(token); // 放回无效的令牌
                return false; // 没有可用的令牌
            }
        }
    }

    private void refill() {
   
        long now = System.currentTimeMillis();
        long tokensToAdd = (now - lastRefillTimestamp + refillPeriod - 1) / refillPeriod * refillTokens;
        lastRefillTimestamp = now;
        currentTokens = Math.min(maxTokens, currentTokens + tokensToAdd);

        for (int i = 0; i < tokensToAdd; i++) {
   
            tokenBucket.offer(now);
        }
    }
}

使用这个RateLimiter类,可以在需要限流的地方调用tryAcquire()方法,如果返回true,则表示有可用的令牌,可以继续处理请求;如果返回false,则表示没有可用的令牌,可以选择拒绝请求或者排队等待。
Java限流算法主要包括以下几种:

  1. 固定窗口算法:这种算法通过一个支持原子操作的计数器来累计一定时间窗口内的请求次数。当请求次数达到设定的阈值时,触发拒绝策略。每过一个时间窗口,计数器重置为0重新开始计数[^2^]。

  2. 滑动窗口算法:这是对固定窗口算法的改进。在滑动窗口算法中,窗口的大小是固定的,但起止时间是动态的。它将一个大的时间窗口分割成多个小的子窗口,每个子窗口单独计数,所有子窗口的计数之和不超过整体阈值。当新请求的时间点超过时间窗口的右边界时,窗口向右移动一个小窗口的距离,最左边的小窗口的计数值被舍弃[^3^][^4^]。

  3. 漏桶算法:漏桶算法将请求看作是流入的水,水桶容量有限,水以恒定的速率流出。如果水桶满了,新的请求(水)就会被丢弃。这种方法可以平滑突发流量,保证流量以相对稳定的速率处理[^5^]。

  4. 令牌桶算法:令牌桶算法通过一个令牌桶来控制请求的速率。系统以一定的速率向桶中添加令牌,当有请求到达时,需要从桶中取出一个令牌才能继续处理。如果桶中没有令牌,请求要么排队等待,要么被直接拒绝。这种方法既可以控制请求的突发流量,又可以允许一定程度的突发请求处理[^5^]。

总的来说,这些算法各有优缺点,适用于不同的场景。选择合适的限流算法取决于具体的应用需求、系统性能要求以及预期的流量模式。

目录
相关文章
|
11天前
|
安全 Java API
Java Web 在线商城项目最新技术实操指南帮助开发者高效完成商城项目开发
本项目基于Spring Boot 3.2与Vue 3构建现代化在线商城,涵盖技术选型、核心功能实现、安全控制与容器化部署,助开发者掌握最新Java Web全栈开发实践。
147 1
|
1月前
|
前端开发 Java API
2025 年 Java 全栈从环境搭建到项目上线实操全流程指南:Java 全栈最新实操指南(2025 版)
本指南涵盖2025年Java全栈开发核心技术,从JDK 21环境搭建、Spring Boot 3.3实战、React前端集成到Docker容器化部署,结合最新特性与实操流程,助力构建高效企业级应用。
459 1
|
11天前
|
人工智能 Java 开发者
阿里出手!Java 开发者狂喜!开源 AI Agent 框架 JManus 来了,初次见面就心动~
JManus是阿里开源的Java版OpenManus,基于Spring AI Alibaba框架,助力Java开发者便捷应用AI技术。支持多Agent框架、网页配置、MCP协议及PLAN-ACT模式,可集成多模型,适配阿里云百炼平台与本地ollama。提供Docker与源码部署方式,具备无限上下文处理能力,适用于复杂AI场景。当前仍在完善模型配置等功能,欢迎参与开源共建。
387 1
阿里出手!Java 开发者狂喜!开源 AI Agent 框架 JManus 来了,初次见面就心动~
|
1月前
|
JavaScript Java 微服务
现代化 Java Web 在线商城项目技术方案与实战开发流程及核心功能实现详解
本项目基于Spring Boot 3与Vue 3构建现代化在线商城系统,采用微服务架构,整合Spring Cloud、Redis、MySQL等技术,涵盖用户认证、商品管理、购物车功能,并支持Docker容器化部署与Kubernetes编排。提供完整CI/CD流程,助力高效开发与扩展。
314 63
|
10天前
|
IDE 安全 Java
Lombok 在企业级 Java 项目中的隐性成本:便利背后的取舍之道
Lombok虽能简化Java代码,但其“魔法”特性易破坏封装、影响可维护性,隐藏调试难题,且与JPA等框架存在兼容风险。企业级项目应优先考虑IDE生成、Java Records或MapStruct等更透明、稳健的替代方案,平衡开发效率与系统长期稳定性。
87 1
|
1月前
|
存储 缓存 安全
Java集合框架(二):Set接口与哈希表原理
本文深入解析Java中Set集合的工作原理及其实现机制,涵盖HashSet、LinkedHashSet和TreeSet三大实现类。从Set接口的特性出发,对比List理解去重机制,并详解哈希表原理、hashCode与equals方法的作用。进一步剖析HashSet的底层HashMap实现、LinkedHashSet的双向链表维护顺序特性,以及TreeSet基于红黑树的排序功能。文章还包含性能对比、自定义对象去重、集合运算实战和线程安全方案,帮助读者全面掌握Set的应用与选择策略。
144 23
|
25天前
|
SQL Java 数据库连接
区分iBatis与MyBatis:两个Java数据库框架的比较
总结起来:虽然从技术角度看,iBATIS已经停止更新但仍然可用;然而考虑到长期项目健康度及未来可能需求变化情况下MYBATISS无疑会是一个更佳选择因其具备良好生命周期管理机制同时也因为社区力量背书确保问题修复新特征添加速度快捷有效.
64 12
|
1月前
|
存储 缓存 安全
Java集合框架(三):Map体系与ConcurrentHashMap
本文深入解析Java中Map接口体系及其实现类,包括HashMap、ConcurrentHashMap等的工作原理与线程安全机制。内容涵盖哈希冲突解决、扩容策略、并发优化,以及不同Map实现的适用场景,助你掌握高并发编程核心技巧。
|
1月前
|
安全 Java 开发者
Java集合框架:详解Deque接口的栈操作方法全集
理解和掌握这些方法对于实现像浏览器后退功能这样的栈操作来说至关重要,它们能够帮助开发者编写既高效又稳定的应用程序。此外,在多线程环境中想保证线程安全,可以考虑使用ConcurrentLinkedDeque,它是Deque的线程安全版本,尽管它并未直接实现栈操作的方法,但是Deque的接口方法可以相对应地使用。
118 12
|
11天前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。