令牌桶算法示例(java实现)

import java.util.concurrent.atomic.AtomicInteger;

public class TokenTask {
    private  final int capacity; //令牌桶容量
    private final int refillRate;//令牌桶补充速率
    private final AtomicInteger tokens;//使用原子类来保证线程安全,表示当前令牌中的令牌数量。
    private long lastRefillTimestamp;//表示上次令牌桶补充的时间戳

    public TokenTask(int capacity, int refillRate) {
        this.capacity = capacity;
        this.refillRate = refillRate;
        this.tokens = new AtomicInteger(capacity);
        this.lastRefillTimestamp = System.nanoTime();
    }
    public synchronized boolean tryConsume(int numTokens){
        refill();
        if(tokens.get()>=numTokens){
            tokens.addAndGet(-numTokens);
            return true;
        }else {
            return false;
        }
    }
    private  void refill(){
        long now = System.nanoTime();
        long refillTokens = (now - lastRefillTimestamp) / 1_000_000_000 * refillRate;
        if(refillTokens>0){
            int newTokens=Math.min(capacity,tokens.get()+(int)refillTokens);
            tokens.set(newTokens);
            lastRefillTimestamp=now;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TokenTask tokenTask = new TokenTask(10, 1);

        //模拟
        System.out.println(tokenTask.tryConsume(1)); //true
        System.out.println(tokenTask.tryConsume(10));
        System.out.println(tokenTask.tryConsume(8));
        Thread.sleep(3000);
        System.out.println(tokenTask.tryConsume(1)); // true

    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
令牌算法是一种限流算法,它可以控制某个服务或接口的并发访问数量,防止系统被过多的请求占用,导致系统负载过高。下面是Java实现令牌算法示例代码: ``` public class TokenBucket { private long capacity; // 桶的容量 private long rate; // 令牌放置速度 private long tokens; // 当前令牌数量 private long lastRefillTime; // 上次放置令牌的时间 public TokenBucket(long capacity, long rate) { this.capacity = capacity; this.rate = rate; this.tokens = capacity; this.lastRefillTime = System.currentTimeMillis(); } /** * 尝试获取令牌 * @return 是否获取到令牌 */ public synchronized boolean tryAcquire() { refill(); if (tokens > 0) { tokens--; return true; } return false; } /** * 放置令牌 */ private void refill() { long now = System.currentTimeMillis(); if (tokens < capacity) { long tokensToAdd = (now - lastRefillTime) * rate / 1000; tokens = Math.min(tokens + tokensToAdd, capacity); } lastRefillTime = now; } } ``` 在这个示例中,令牌算法的核心在于 `tryAcquire()` 方法,它用于尝试获取令牌。在这个方法中,我们首先调用 `refill()` 方法,用于放置令牌。然后判断桶中是否有令牌,如果有,就将令牌数量减一,并返回获取到令牌;否则返回获取不到令牌。 放置令牌的方法 `refill()` 会计算两次放置令牌之间的时间差,根据时间差和令牌的放置速度计算出应该放置的令牌数量。如果桶中令牌数量小于容量,就将放置的令牌数量和当前令牌数量相加,但不超过桶的容量。这样就可以保证令牌桶中的令牌数量不会超过容量。 使用令牌算法可以有效地限制系统的并发访问数量,避免系统负载过高导致服务不稳定。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值