令牌桶算法优化实现

上篇文章详细阐述了令牌桶算法的优缺点,并且针对不足之处也给出一个简单的优化方案。有了设计思路,接下来实现便相对容易很多。
首先用代码实现令牌桶算法,创建一个令牌桶类。

public class TokenBucket
{
    private final long capacity;
    private final long refillTokensPerOneMillis;
    private AtomicLong availableTokens;
    private AtomicLong lastRefillTimestamp;
    public TokenBucket(long capacity, long refillTokensPerOneMillis) {
        this.capacity = capacity;
        this.refillTokensPerOneMillis = refillTokensPerOneMillis;
        this.availableTokens = new AtomicLong(capacity);
        this.lastRefillTimestamp = new AtomicLong(System.currentTimeMillis());
    }
    public synchronized boolean tryConsume(long numTokens)
    {        refill();
        if (availableTokens.get() >= numTokens)
        {
            availableTokens.addAndGet(-numTokens);
            return true;
        }
        return false;
    }
    private void refill() {
        long currentTimeMillis = System.currentTimeMillis();
        long timeSinceLastRefill = currentTimeMillis - lastRefillTimestamp.get();
        long tokensToRefill = timeSinceLastRefill * refillTokensPerOneMillis;
        if (tokensToRefill > 0) {
            availableTokens.addAndGet(tokensToRefill);
            availableTokens.set(Math.min(capacity, availableTokens.get()));
            lastRefillTimestamp.set(currentTimeMillis);
        }
    }
}

然后开启多线程使用该算法。
改进之处在于,首先注入ServerBean ,然后通过该对象调用函数查询数据库获取服务器负载值,得到负载值后,根据负载值大小,来动态调整令牌生成数量。

 public void tokenMethod()
       {
           ServerBean serverLBIndex = serverService.getServerLBIndex();
           Float min = serverLBIndex.getServerLB();
           System.out.println("当前最小lb:"+serverLBIndex.getServerLB());
           int flag = 1;//令牌数量可以根据实际情况动态调整
           if(min > 0.8)
           {
               flag = 1;
           }else if(min < 0.4){
               flag = 3;
           }else{
               flag = 2;
           }
           System.out.println(flag);
           TokenBucket tokenBucket = new TokenBucket(100, flag);        // flag取代了传统固定生成令牌数量,而是动态调整
           for (int i = 0; i < 10; i++) {
           
               new Thread(() -> {
                   while (true) {
                       if (tokenBucket.tryConsume(50)) {
                           System.out.println(Thread.currentThread().getName() + " 执行请求");

                       }
                       else {
                           System.out.println(Thread.currentThread().getName() + " 请求被限流");                    }
                       try {                    // 每个线程等待100毫秒后尝试再次请求
                           Thread.sleep(100);                    }
                       catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                   }
               }, "线程" + i).start();
           }
       }

这样一个简单的优化方案便实现完成。如果有大佬有别的优化方案欢迎在评论区留言!!!

  • 21
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值