限流算法java实现

参考教程:2小时吃透4种分布式限流算法

1.计数器限流

java 复制代码
public class CounterLimiter {

    // 开始时间
    private static long startTime = System.currentTimeMillis();
    // 时间间隔,单位为ms
    private long interval = 1000L;
    // 限制访问次数
    private int limitCount = 2;
    // 访问次数
    private int reqCount = 0;

    private synchronized boolean tryAcquire(){
        long nowTime = System.currentTimeMillis();
        if(nowTime < startTime + interval){
            if(reqCount + 1 > limitCount){
                System.out.println(Thread.currentThread().getName() + "被限流了");
                return true;
            }
            reqCount++;
            System.out.println(Thread.currentThread().getName() + "通过了");
            return false;
        }else {
            reqCount = 1;
            startTime = nowTime;
            System.out.println(Thread.currentThread().getName() + "通过了");
            return false;
        }
    }

    public static void main(String[] args) {
        CounterLimiter counterLimiter = new CounterLimiter();
        for (int i = 0; i < 10; i++) {
            new Thread(() ->{
                counterLimiter.tryAcquire();
            }).start();
        }
    }

}

2.滑动时间窗口限流

java 复制代码
import java.util.LinkedList;

public class SlidingTimeWindowLimiter {
    // 请求数量
    private int reqCount;
    // 窗口集合
    private LinkedList<Integer> slots = new LinkedList<>();
    // 限制访问量
    private int limitNum = 2;
    // 窗口数量
    private int windowNum = 100;
    // 每个窗口的时间范围,单位ms
    private long windowLength = 100L;

    public synchronized Boolean limit(){
        if(reqCount + 1 > limitNum){
            System.out.println(Thread.currentThread().getName() + ": 被拦截了");
            return true;
        }
        reqCount++;
        slots.set(slots.size() - 1, slots.peekLast() + 1);
        System.out.println(Thread.currentThread().getName() + ": 通过了");
        return false;
    }
    public SlidingTimeWindowLimiter(){
        slots.addLast(0);
        new Thread(() -> {
            while (true){
                try {
                    Thread.sleep(windowLength);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                slots.addLast(0);
                if(slots.size() > windowNum){
                    reqCount = reqCount - slots.peekLast();
                    slots.removeLast();
                    System.out.println("滑动格子:" + reqCount);
                }
            }
        }).start();

    }

    public static void main(String[] args) {
        SlidingTimeWindowLimiter slidingTimeWindowLimiter = new SlidingTimeWindowLimiter();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                slidingTimeWindowLimiter.limit();
            }).start();
        }
    }

}

3.漏桶算法

java 复制代码
public class LeakyBucketLimiter {
    // 初始时间
    private long timestamp = System.currentTimeMillis();
    // 漏桶容量
    private long capacity = 5;
    // 流出速率
    private long rate = 10;
    // 桶内有多少请求
    private long water = 0;

    public synchronized Boolean limit(){
        long now = System.currentTimeMillis();
        water = Math.max(0, water - (now - timestamp) / 1000 * rate);
        timestamp = now;
        if((water + 1) <= capacity){
            water++;
            System.out.println(Thread.currentThread().getName() + "通过了");
            return false;
        }else{
            System.out.println(Thread.currentThread().getName() + "被拦截了");
            return true;
        }
    }

    public static void main(String[] args) {
        LeakyBucketLimiter counterLimiter = new LeakyBucketLimiter();
        for (int i = 0; i < 10; i++) {
            new Thread(() ->{
                counterLimiter.limit();
            }).start();
        }
    }

}

4.令牌桶算法

java 复制代码
public class TokenBucketLimiter {
    // 初始时间
    private long timeStamp = System.currentTimeMillis();
    // 令牌桶容量
    private long capacity = 5;
    // 每秒生成令牌的数量
    private long rate  = 2;
    // 桶内的令牌数
    private long tokens = 0;

    public synchronized Boolean limit(){
        long now = System.currentTimeMillis();
        tokens = Math.min(capacity, tokens + (now - timeStamp) * rate);
        timeStamp = now;
        // 没有令牌了
        if(tokens < 1){
            System.out.println(Thread.currentThread().getName() + "被拦截了");
            return true;
        }else {
            tokens--;
            System.out.println(Thread.currentThread().getName() + "通过了");
            return false;
        }
    }
    public static void main(String[] args) {
        TokenBucketLimiter slidingTimeWindowLimiter = new TokenBucketLimiter();
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                slidingTimeWindowLimiter.limit();
            }).start();
        }
    }
}
相关推荐
Baron X16 分钟前
Eclipse Temurin 21 (JRE) Alpine 镜像获取、离线导入与推送操作
java·docker·eclipse·temurin
孙浩君29 分钟前
我用 Spring Boot + xterm.js 写了个终端风格互动叙事游戏引擎:游戏即文件,上传一个 JSON 就能玩
java
jose37 分钟前
URL 里多写了一个端口,为什么请求还能调通?
java·后端
孙浩君40 分钟前
我用 Spring Boot 写了个「终端风格模拟经营游戏引擎」:引擎 + JSON 游戏文件,开箱即玩
java
y1su1 小时前
Leetcode 动态规划 模板
java·数据结构·算法·leetcode·动态规划
Wang's Blog1 小时前
Java 项目实战: 交友项目 - JWT 概述:为什么要用 Token 换掉 Session
java·ui·交友
SL_staff2 小时前
低代码选型避坑指南:为什么‘能拖拽’不等于‘能交付’?——基于JVS八大引擎的四维交付能力评估框架
java·低代码·spring cloud
李福春2 小时前
技术思考问题6:技术演讲该晒成功架构,还是交代失败与取舍?
java·开发语言·架构·computer use·深圳同盟·腾讯云架构师技术同盟·反演思维