首页 > 编程语言 >Java限流功能的实现

Java限流功能的实现

时间:2024-01-05 19:02:17浏览次数:37  
标签:功能 capacity int 令牌 private 限流 Java public

在Java中,限流是一种常见的技术手段,用于控制系统的访问速率,以保护系统免受过载和滥用。以下是一些常见的Java限流实现方法:

  1.计数器限流

  这是一种简单而常见的限流方法。在该方法中,我们可以使用计数器来记录每个时间窗口内的请求数量,并与预设的阈值进行比较。如果请求数量超过阈值,就拒绝进一步的请求。

  使用时,我们可以在关键代码路径上调用allowRequest()方法,并根据返回值决定是否允许请求继续进行。

public class CounterLimiter {
    private int limit;
    private AtomicInteger counter;

    public CounterLimiter(int limit) {
        this.limit = limit;
        this.counter = new AtomicInteger(0);
    }

    public boolean allowRequest() {
        int currentCount = counter.incrementAndGet();
        if (currentCount > limit) {
            counter.decrementAndGet();
            return false;
        }
        return true;
    }
}

  2.令牌桶限流

  令牌桶算法是一种基于队列的限流算法。在令牌桶中,我们可以定义一个固定大小的令牌桶,该桶以固定速率生成令牌。每当一个请求到达时,它需要获取一个令牌才能执行。如果令牌桶中没有可用的令牌,请求将被暂时阻塞或丢弃。

public class TokenBucketLimiter {
    private int capacity;
    private int tokens;
    private long lastRefillTimestamp;
    private double refillRate;
    private Object lock = new Object();

    public TokenBucketLimiter(int capacity, double refillRate) {
        this.capacity = capacity;
        this.tokens = capacity;
        this.refillRate = refillRate;
        this.lastRefillTimestamp = System.currentTimeMillis();
    }

    public boolean allowRequest() {
        synchronized (lock) {
            refillTokens();
            if (tokens > 0) {
                tokens--;
                return true;
            }
            return false;
        }
    }

    private void refillTokens() {
        long currentTime = System.currentTimeMillis();
        double elapsedTime = (currentTime - lastRefillTimestamp) / 1000.0;
        int newTokens = (int) (elapsedTime * refillRate);
        if (newTokens > 0) {
            tokens = Math.min(tokens + newTokens, capacity);
            lastRefillTimestamp = currentTime;
        }
    }
}

  在这个示例中,capacity表示令牌桶的最大容量,refillRate表示每秒生成的令牌数量。使用时,我们可以在关键代码路径上调用allowRequest()方法,并根据返回值决定是否允许请求继续进行。

  3.漏桶限流

  漏桶算法是一种基于队列的限流算法,类似于令牌桶算法。在漏桶中,请求被看作水滴,它们以固定速率流入桶中,然后以固定速率从桶中流出。如果桶已满,则多余的请求将被拒绝或丢弃。

public class LeakyBucketLimiter {
    private int capacity;
    private int availableTokens;
    private long lastLeakTimestamp;
    private double leakRate;
    private Object lock = new Object();

    public LeakyBucketLimiter(int capacity, double leakRate) {
        this.capacity = capacity;
        this.availableTokens = 0;
        this.leakRate = leakRate;
        this.lastLeakTimestamp = System.currentTimeMillis();
    }

    public boolean allowRequest() {
        synchronized (lock) {
            leakTokens();
            if (availableTokens > 0) {
                availableTokens--;
                return true;
            }
            return false;
        }
    }

    private void leakTokens() {
        long currentTime = System.currentTimeMillis();
        double elapsedTime = (currentTime - lastLeakTimestamp) / 1000.0;
        int tokensToLeak = (int) (elapsedTime * leakRate);
        if (tokensToLeak > 0) {
            if (tokensToLeak >= availableTokens) {
                availableTokens = 0;
            } else {
                availableTokens -= tokensToLeak;
            }
            lastLeakTimestamp = currentTime;
        }
    }
}

  在这个示例中,capacity表示桶的最大容量,leakRate表示每秒流出的水滴数量。使用时,我们可以在关键代码路径上调用allowRequest()方法,并根据返回值决定是否允许请求继续进行。

  这些是一些常见的Java限流实现方法,我们可以根据具体的需求选择适合我们的场景的方法。此外,还有其他更复杂和高级的限流算法可用,例如漏斗算法、SmoothWarmingUp算法等。这些等下期再给大家列举一二。

标签:功能,capacity,int,令牌,private,限流,Java,public
From: https://blog.51cto.com/u_12266412/9116728

相关文章

  • 时代变了,Spring 官方抛弃了 Java 8!
    先容许我吐槽一句:Spring官方,窝草nm!原谅我很愤怒!最近编程导航星球和群友们反复问一个问题:为啥用IDEA创建SpringBoot项目时,不能选择Java8了?我本来以为是IDEA版本更新导致的Bug,开始还没在意。直到我今天自己初始化项目时才发现:卧槽,Java8真没了?!具体一点,应该是使用IDEA......
  • 【从零开始重学Java】第3天
    前情提示从零开始重学Java第0天从零开始重学Java第1天从零开始重学Java第2天表达式和流程控制语句表达式操作数常量(只有简单数据类型和String)变量运算符位运算只对字符char和整型生效Java里<<(算术)左移>>(算术)右移>>>无符号(逻辑)右移运算符优先......
  • JAVA方法重载(函数)
    [JAVA方法]方法重载重载指的是多个方法名称相同,但参数列表不同参数列表不同分为:参数个数不同参数类型不同参数的多类型顺序不同注意事项一个表达式中的最后结果以数据类型范围大的为结果的数据类型。无法因为返回值类型不同进行重载。参数传递对于引用类......
  • JavaScript——函数的call、apply、bind方法
    JavaScript的函数拥有三个方法:callapplybind这三个方法都可以改变函数被调用时,函数内部this的指向。至于区别,阅读下面代码即可一目了然:functionmyCall(context){constargs=[...arguments].slice(1)letresultcontext=context?context:window......
  • java 包和访问修饰符
    免责声明:java基础资料均来自于韩顺平老师的《循序渐进学Java零基础》教案,具体视频内容可以去B站观看,这些资料仅用于学习交流,不得转载用于商业活动java包和访问修饰符1.1包包的三大作用区分相同名字的类当类很多时,可以很好的管理类控制访问范围基本语法:pagckagecom.tes......
  • java面向对象:类(二)
    1.Java面向对象:类1.1作用域1.1.1基本使用面向对象中,变量作用域是非常重要的知识点在java编程中,主要的变量就是属性(成员变量)和局部变量我们所获得局部变量一般是指在成员方法中定义得变量java中作用域得分类:全局变量:也就是属性,作用域为整个类,可以不赋值,直接使用,因为有默......
  • JavaScript——数组的归并方法
    JavaScript的reduce和reduceRight的作用是通过遍历数组得到一个结果,原理如下:functionmyReduce(execute,initValue){constlength=this.lengthletresultfor(leti=0;i<length;i++){if(i===0){consthasInitValue=initV......
  • Java基础语法(下):程序流程控制
    程序流程控制顺序结构分支结构分支语句1:if-else结构if-else使用说明1、条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量2、语句块只有一条执行语句时,一对{}可以省略,但建议保留3、if-else语句结构,根据需要可以嵌套使用4、当if-else结构是“多选一”时,最......
  • Java编译原理
    概述java语言的"编译期"分为前端编译和后端编译两个阶段。前端编译是指把*.java文件转变成*.class文件的过程;后端编译(JIT,JustInTimeCompiler)是指把字节码转变成机器码的过程。在编译原理中,将源代码编译成机器码,主要经过下面几个步骤:Java中的前端编译java的前端......
  • java定时任务执行器
    ScheduledExecutorServiceexecutorService=Executors.newSingleThreadScheduledExecutor();这段代码使用Java的 ScheduledExecutorService 接口和 Executors 类来创建一个单线程的定时任务执行器。具体来说,Executors.newSingleThreadScheduledExecutor() 方法返回一......