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;
}
}
}
05-02
5489
08-06
2667
07-08
288