RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率。
通常可应用于抢购限流防止冲垮系统;限制某接口、服务单位时间内的访问量,譬如一些第三方服务会对用户访问量进行限制;限制网速,单位时间内只允许上传下载多少字节等。
下面是限制每秒钟最大能有10个获取token:
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.RateLimiter;
public class Test {
RateLimiter rateLimiter = RateLimiter.create(10);
public static void main(String[] args) {
Test t = new Test();
ExecutorService s = Executors.newFixedThreadPool(20);
CountDownLatch countDownLatch = new CountDownLatch(1);
Random random = new Random(10);
for (int i = 0; i < 20; i++) {
s.submit(new Runnable() {
@Override
public void run() {
try {
countDownLatch.await();
TimeUnit.MILLISECONDS.sleep(random.nextInt(1000));
t.seckill();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
});
}
countDownLatch.countDown();
s.shutdown();
}
public void seckill() {
if (rateLimiter.tryAcquire()) {
System.out.println(Thread.currentThread().getName() + ": 我抢到了");
} else {
System.out.println(Thread.currentThread().getName() + ": 我没抢到");
}
}
}
运行结果:
下面是限制每秒钟只能获取一个token,20个线程需要20秒才能获取完
RateLimiter rateLimiter = RateLimiter.create(10);
public static void main(String[] args) {
Test t = new Test();
ExecutorService s = Executors.newFixedThreadPool(20);
CountDownLatch countDownLatch = new CountDownLatch(1);
for (int i = 0; i < 20; i++) {
s.submit(new Runnable() {
@Override
public void run() {
try {
countDownLatch.await();
t.seckill();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
});
}
countDownLatch.countDown();
s.shutdown();
}
public void seckill() {
System.out.println("我抢到了,耗时: " + rateLimiter.acquire() );
}
运行结果: