guava-SmoothRateLimiter代码

 


//定义为volatile变量
private volatile Object mutexDoNotUseDirectly;
//已存储许可证数量
double storedPermits;
//最大许可证数量
double maxPermits;
//间隔时间
double stableIntervalMicros;
//上一次获取许可证时间戳
private long nextFreeTicketMicros;

//double check
private Object mutex() {
Object mutex = this.mutexDoNotUseDirectly;
if (mutex == null) {
synchronized (this) {
       //优化点
mutex = this.mutexDoNotUseDirectly;
if (mutex == null) {
this.mutexDoNotUseDirectly = mutex = new Object();
}
}
}

return mutex;
}

//阻塞方式获取许可证
public double acquire(int permits) {
// 计算获取令牌所需等待的时间
long microsToWait = reserve(permits);
stopwatch.sleepMicrosUninterruptibly(microsToWait);
return 1.0 * microsToWait / SECONDS.toMicros(1L);
}

//
final long reserve(int permits) {
checkPermits(permits);
synchronized (mutex()) {
return reserveAndGetWaitLength(permits, stopwatch.readMicros());
}
}

//
final long reserveAndGetWaitLength(int permits, long nowMicros) {
// 计算从当前时间开始,能够获取到目标数量令牌时的时间
long momentAvailable = reserveEarliestAvailable(permits, nowMicros);
// 两个时间相减,获得需要等待的时间
return max(momentAvailable - nowMicros, 0);
}

//
final long reserveEarliestAvailable(int requiredPermits, long nowMicros) {
// 刷新令牌数,相当于每次acquire时在根据时间进行令牌的刷新
this.resync(nowMicros);

long returnValue = this.nextFreeTicketMicros;
// 获取当前已有的令牌数和需要获取的目标令牌数进行比较,计算出可以目前即可得到的令牌数。
double storedPermitsToSpend = Math.min((double) requiredPermits, this.storedPermits);
// freshPermits是需要预先支付的令牌,也就是目标令牌数减去目前即可得到的令牌数
double freshPermits = (double) requiredPermits - storedPermitsToSpend;
// 因为会突然涌入大量请求,而现有令牌数又不够用,因此会预先支付一定的令牌数
// waitMicros即是产生预先支付令牌的数量时间,则将下次要添加令牌的时间应该计算时间加上watiMicros
long waitMicros = this.storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend) + (long) (freshPermits * this.stableIntervalMicros);
// 更新nextFreeTicketMicros,本次预先支付的令牌所需等待的时间让下一次请求来实际等待。
this.nextFreeTicketMicros = LongMath.saturatedAdd(this.nextFreeTicketMicros, waitMicros);
this.storedPermits -= storedPermitsToSpend;
return returnValue;
}

 

posted @ 2024-04-25 16:09  使用D  阅读(10)  评论(0编辑  收藏  举报