本文基于 Guava-18.0.jar 。
0. 概述
RateLimiter
是令牌桶思想的一个实现,可实现流量整形、资源访问速率控制。
与信号量对比:
- 一旦从
RateLimiter
获得许可,不需要释放。信号量分配后必须释放。 RateLimiter
控制的是速率,以配置的速率分发许可,速率不变时单位时间内分发的许可量是恒定的。信号量控制的是并发访问的数量,单位时间内分配的次数跟使用许可的时长有关,每次申请使用的时间越短,则单位时间内能分配的次数就越多。
对 RateLimiter
请求许可的数量不会对请求本身产生抑制影响,但会对下一个请求产生抑制。例如一个请求很大数量许可的请求到达空闲 RateLimiter
时,它将马上获得许可,但下一个请求会被抑制,从而为前面昂贵的请求付出代价。
从 RateLimiter
申请许可时,可能会阻塞、也可能不会,是否阻塞取决于上一次分配许可的时间和当前请求的许可数量。
RateLimiter
可以配置一个 warnup 热身周期,在这个周期内每秒发出的许可数量稳步增长直至达到稳定的速率。简单说是慢启动吧。
1. 使用示例:
// 每秒2个的速率提交任务
final RateLimiter rateLimiter = RateLimiter.create(2.0);
void submitTasks(List tasks, Executor executor) {
for (Runnable task : tasks) {
rateLimiter.acquire(); // may wait
executor.execute(task);
}
}