限流算法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();
        }
    }
}
相关推荐
豆沙沙包?15 分钟前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
年老体衰按不动键盘40 分钟前
快速部署和启动Vue3项目
java·javascript·vue
咖啡啡不加糖1 小时前
Redis大key产生、排查与优化实践
java·数据库·redis·后端·缓存
liuyang-neu1 小时前
java内存模型JMM
java·开发语言
UFIT1 小时前
NoSQL之redis哨兵
java·前端·算法
刘 大 望1 小时前
数据库-联合查询(内连接外连接),子查询,合并查询
java·数据库·sql·mysql
怀旧,1 小时前
【数据结构】6. 时间与空间复杂度
java·数据结构·算法
大春儿的试验田2 小时前
Parameter ‘XXX‘ not found. Available parameters are [list, param1]
java
程序员JerrySUN3 小时前
[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
java·linux·架构
2302_809798323 小时前
【JavaWeb】Docker项目部署
java·运维·后端·青少年编程·docker·容器