限流是一种常见的保护系统的方式,它可以防止系统过载和资源浪费。Java中实现限流的方式有很多种,下面介绍几种常用的实现方式。

  1. 计数器限流

计数器限流是最简单的一种限流方式,它的实现原理是在一段时间内计算请求次数,当超过限定的阈值时就拒绝请求。具体实现可以通过在内存中维护一个计数器,每次请求时增加计数器的值,超过阈值时就拒绝请求。

示例代码:

public class CounterLimiter {
    private int limit; // 限流阈值
    private int count = 0; // 当前请求数
    private long timestamp = System.currentTimeMillis(); // 时间戳

    public CounterLimiter(int limit) {
        this.limit = limit;
    }

    public synchronized boolean tryAcquire() {
        // 如果时间间隔大于1秒,则重置计数器和时间戳
        if (System.currentTimeMillis() - timestamp > 1000) {
            count = 0;
            timestamp = System.currentTimeMillis();
        }
        // 如果请求数小于限流阈值,则允许通过
        if (count < limit) {
            count++;
            return true;
        }
        return false; // 超过限流阈值,拒绝请求
    }
}
  1. 令牌桶限流

令牌桶限流是一种常用的限流算法,它的实现原理是在一段时间内生成固定数量的令牌,每次请求需要获取一个令牌才能通过。如果令牌不足,则拒绝请求。具体实现可以用一个队列来存储令牌,每次请求时从队列中获取一个令牌,如果队列为空则拒绝请求。

示例代码:

public class TokenBucketLimiter {
    private int limit; // 限流阈值
    private Queue<Long> tokens = new LinkedList<>(); // 令牌队列

    public TokenBucketLimiter(int limit) {
        this.limit = limit;
        // 初始化令牌队列
        for (int i = 0; i < limit; i++) {
            tokens.offer(System.currentTimeMillis());
        }
    }

    public synchronized boolean tryAcquire() {
        // 如果令牌队列不为空,则允许通过
        if (!tokens.isEmpty()) {
            long token = tokens.poll();
            long now = System.currentTimeMillis();
            if (now - token < 1000) {
                return true;
            }
        }
        return false; // 令牌不足,拒绝请求
    }
}
  1. 漏桶限流

漏桶限流是一种常用的限流算法,它的实现原理是将请求均匀地放入一个固定容量的桶中,如果桶满了则拒绝请求。具体实现可以用一个队列来存储请求,每次请求时从队列中取出一个请求,如果队列为空则拒绝请求。

示例代码:

public class LeakyBucketLimiter {
    private int limit; // 限流阈值
    private Queue<Long> requests = new LinkedList<>(); // 请求队列
    private long timestamp = System.currentTimeMillis(); // 时间戳

    public LeakyBucketLimiter(int limit) {
        this.limit = limit;
    }

    public synchronized boolean tryAcquire() {
        // 计算漏桶流出的请求数
        long now = System.currentTimeMillis();
        int leaked = (int) ((now - timestamp) / 1000 * limit);
        if (leaked > 0) {
            timestamp = now;
            // 移除漏桶流出的请求数
            while (!requests.isEmpty() && leaked > 0) {
                requests.poll();
                leaked--;
            }
        }
        // 如果请求队列不满,则允许通过
        if (requests.size() < limit) {
            requests.offer(System.currentTimeMillis());
            return true;
        }
        return false; // 桶满了,拒绝请求
    }
}

以上三种方式都可以实现限流,选择哪种方式取决于具体的业务场景和需求。同时也可以将多种限流方式组合使用,以达到更好的限流效果

用JAVA实现限流逻辑

原文地址: https://www.cveoy.top/t/topic/eDmu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录