限流算法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();
        }
    }
}
相关推荐
Hx_Ma165 小时前
SpringMVC框架提供的转发和重定向
java·开发语言·servlet
期待のcode5 小时前
原子操作类LongAdder
java·开发语言
舟舟亢亢6 小时前
Java集合笔记总结
java·笔记
小酒窝.6 小时前
【多线程】多线程打印ABC
java
乡野码圣6 小时前
【RK3588 Android12】RCU机制
java·jvm·数据库
JAVA+C语言7 小时前
如何优化 Java 多主机通信的性能?
java·开发语言·php
编程彩机8 小时前
互联网大厂Java面试:从分布式架构到大数据场景解析
java·大数据·微服务·spark·kafka·分布式事务·分布式架构
小酒窝.8 小时前
【多线程】多线程打印1~100
java·多线程
君爱学习8 小时前
基于SpringBoot的选课调查系统
java
APIshop8 小时前
Java 实战:调用 item_search_tmall 按关键词搜索天猫商品
java·开发语言·数据库