极客时间:Java并发编程实战
1 高性能限流器GuavaRateLimiter
令牌桶算法:记录一个下一令牌产生的时间,并动态更新它,就能够轻松完成限流功能
与信号量区别:信号量是“一次性可以有多少个线程一起执行”,限流器是“每秒最多允许几个请求通过”“1个请求/xxx秒”
申请令牌时调用acquire方法
1.如果请求时间now在下⼀令牌产⽣时间next之后:
resync:通过(now-next)/interval来新增令牌,并且因为next到now这段时间的令牌发放的逻辑处理完毕了,所以将下一次发放令牌的时间next重置为当前时间now
reserve:然后根据令牌数来判断next:如果令牌桶中还有令牌,则next不用变,减去一个令牌当作被预支了;如果没有则需要变:因为当前next发放的这个令牌会给当前请求使用(sleep掉next-now的时间后再返回,等价于获取此令牌),next需要变为下一个令牌的发放时间,等待下一个请求;
2.如果请求时间now在下⼀令牌产⽣时间next之前:
reserve:同上
class SimpleLimiter {
//当前令牌桶中的令牌数量
long storedPermits = 0;
//令牌桶的容量
long maxPermits = 3;
//下⼀令牌产⽣时间
long next = System.nanoTime();
//发放令牌间隔:纳秒
long interval = 1000_000_000;
//请求时间在下⼀令牌产⽣时间之后,则
// 1.重新计算令牌桶中的令牌数
// 2.将下⼀个令牌发放时间重置为当前时间
void resync(long now) {
if (now > next) {