public class LocalTest {
@Test
public void test(){
//桶大小为100 没秒填充100个 时间单位为毫秒 1s = 1000ms
TokenBucket limiter = new TokenBucket(100, 100, 1000);
}
}
class TokenBucket {
//令牌桶大小
private final long capacity;
//填充速度 没毫秒填充多少个
private final double refillTokensPerOneMillis;
//桶中还剩多少个令牌
private double availableTokens;
//上一次填充的时间
private long lastRefillTimestamp;
public TokenBucket(long capacity, long refillTokens, long refillPeriodMillis) {
//令牌桶大小
this.capacity = capacity;
// 每秒填充100 / 1000 = 每毫秒填充多少个
this.refillTokensPerOneMillis = (double) refillTokens / (double) refillPeriodMillis;
//创建时 可用令牌 = 桶大小
this.availableTokens = capacity;
// 填充时间
this.lastRefillTimestamp = System.currentTimeMillis();
}
//同步方法 保证线程安全
synchronized public boolean tryConsume(int numberTokens) {
//刷新令牌桶
refill();
if (availableTokens < numberTokens) {
return false;
} else {
availableTokens -= numberTokens;
return true;
}
}
private void refill() {
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis > lastRefillTimestamp) {
//计算当前和上次时间的时间差
long millisSinceLastRefill = currentTimeMillis - lastRefillTimestamp;
//时间差 * 速度 = 需要生成多少个
double refill = millisSinceLastRefill * refillTokensPerOneMillis;
// 剩余的令牌+新生成的令牌 同时 不能大于 桶大小
this.availableTokens = Math.min(capacity, availableTokens + refill);
//更新生成时间
this.lastRefillTimestamp = currentTimeMillis;
}
}
}
原生令牌桶算法
最新推荐文章于 2025-10-14 23:54:55 发布
该博客介绍了如何实现一个基于令牌桶算法的限流器。`TokenBucket`类包含了令牌桶的主要逻辑,包括桶的容量、填充速度以及令牌的消费。`tryConsume`方法保证了线程安全地消费令牌,而`refill`方法则根据时间差动态补充令牌。这个实现可用于流量控制和防止系统过载。
491

被折叠的 条评论
为什么被折叠?



