一、概念
是不需要释放许可证的。RateLimiter常被用于限制对一些资源的 访问速率,且该速率是可配置的。具体设置方式如下:RateLimiter使用一种“令牌桶“的流控算法,会按照一定的频率往桶里扔令牌,线程只有拿到令牌后才能执行,线程一旦获取到许可证后,
RateLimiter limiter = RateLimiter.create(100); //设置对资源的访问频率为每秒100次(QPS)
二、常用方法介绍
①double acquire();----------------------//从RateLimiter获取一个许可,该方法会被阻塞直到获取到请求
②double acquire();----------------------//从RateLimiter获取指定许可数,该方法会被阻塞直到获取到请求
③boolean tryAcquire();-----------------//从RateLimiter 获取许可,如果该许可可以在无延迟下的情况下立即获取得到的话
④boolean tryAcquire(int permits); ----//从RateLimiter 获取许可数,如果该许可数可以在无延迟下的情况下立即获取得到的话
构造方法如下:
①static RateLimitercreate(double permitsPerSecond);
//根据指定的稳定吞吐率创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少查询)
②static RateLimitercreate(double permitsPerSecond,long warmupPeriod,TimeUnit unit);
//根据指定的稳定吞吐率和预热期来创建RateLimiter,这里的吞吐率是指每秒多少许可数(通常是指QPS,每秒多少个请求量),
//在这段预热时间内,RateLimiter每秒分配的许可数会平稳地增长直到预热期结束时达到其最大速率。(只要存在足够请求数来使其饱和)
三、举例说明
1、使用tryAcquire()方法,在获取不到许可证的情况下,立刻返回
final RateLimiter rateLimiter = RateLimiter.create(2.0);
public ResponseVo getResult(QueryParams params){
if(!rateLimiter.tryAcquire()){ //获取不到许可证就立即放回,不需要等待
return new ResponseVo();
}
}
2、利用线程池来批量执行多任务的时候,可以限制任务执行的速度
final RateLimiter rateLimiter = RateLimiter.create(2.0);
public void executeTasks(TaskLists tasks,Executor executor){
for(task : tasks){
rateLimiter.acquire(); // 在获取不到许可证的情况下,是需要等待的
executor.execute(task);
}
}
四、小结
RateLimiter请求的许可数不会影响到请求本身的限制,但会影响下一次请求的限制,比如如下代码:
RateLimiter limiter = RateLimiter.create(2.0);
limiter.acquire(10);
limiter.acquire(); //会等待将近5s左右的时间
注意:RateLimiter 并不提供公平性的保证
五、参考文献
并发编程网: http://ifeve.com/guava-ratelimiter/http://blog.csdn.net/FoolishAndStupid/article/details/76285690