限流之令牌桶和漏桶算法(java)

令牌桶算法:
令牌桶算法思想:以固定速率产生令牌,放入令牌桶,每次用户请求都得申请令牌,令牌不足则拒绝请求或等待。令牌桶算法可以满足突发请求的情况(一次性可以拿很多token)
代码逻辑:线程池每0.5s发送随机数量的请求,每次请求计算当前的令牌数量,请求令牌数量超出当前令牌数量,则产生限流。

.
.
以下是简单的demon,着重理解大致思路,并发性问题暂忽略不考虑。

@Slf4j
public class TokensLimiter{

    // 桶的容量
    int capacity = 10;

    // 当前令牌数
    int token = 0;

    // 生成令牌的速度12/s
    int rate = 12;

    // 最后一次发放令牌的时间
    long lastTime = System.currentTimeMillis();

    // 创建一个线程池
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

    public void aquire(){

        scheduledExecutorService.scheduleWithFixedDelay(()->{

                    long now = System.currentTimeMillis();

                    // 计算当前令牌数,令牌书最大为桶的容量
                    token = (int) Math.min(capacity,(int) (token + (now-lastTime)*rate/1000));

                    // 每次生成的请求数(每个请求往桶中拿一个令牌)
                    int permits = (int) (Math.random()*9+1);
                    log.info("请求数:"+permits+" 当前桶令牌数:"+token);
                    lastTime = now;

                    if(token <permits){
                        log.info("请求被限流");
                    }else{
                        token-=permits;
                        log.info("当前令牌数"+token);
                    }
                },0,500, TimeUnit.MILLISECONDS);
    }

    public static void main(String[] args) {
        new TokensLimiter().aquire();
    }
}

效果截图:
限流之令牌桶和漏桶算法(java)_第1张图片

漏桶算法
漏桶容量固定,按照固定速率流出水滴;如果桶是空的,不用流,如果桶满了,再流入水滴,则拒绝服务。

@Slf4j
public class LeakyBucket {

    // 桶容量
    int capacity = 10;

    // 当前水容量
    int water = 0;

    // 水流速度7/s
    int rate = 7;

    // 最后一次请求时间
    long lastTime = System.currentTimeMillis();

    // 创建一个线程池
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

    public void aquire(){

         scheduledExecutorService.scheduleWithFixedDelay(()->{

                 // 当前时间
                 long now = System.currentTimeMillis();

                 // 计算当前水量(时间差的水流量)
                 water = (int) Math.max(0,(int) (water - (now-lastTime)/1000*rate));

                 // 每次水滴量(请求数)
                 int permits = (int) (Math.random()*8+1);
                 log.info("请求数:"+permits+" 当前桶余量:"+(capacity-water));

                 lastTime = now;

                 if(capacity-water <permits){
                     log.info("请求被限流");
                 }else{
                     water+=permits;
                     log.info("桶剩余容量:"+(capacity-water));
                 }
             },0,500, TimeUnit.MILLISECONDS);
    }

    public static void main(String[] args) {
        new LeakyBucket().aquire();
    }
}

效果截图:
限流之令牌桶和漏桶算法(java)_第2张图片

你可能感兴趣的:(初阶算法,java,算法,大数据)