前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Guava RateLimiter

Guava RateLimiter

作者头像
技术从心
发布2020-04-21 16:40:24
4430
发布2020-04-21 16:40:24
举报
文章被收录于专栏:技术从心技术从心

来源:https://mrbird.cc/Guava-RateLimiter.html

Google Guava提供的RateLimiter使用的是令牌桶算法。令牌桶算法的基本思想是以固定的速率生成令牌,在执行请求之前都需要从令牌桶里获取足够的令牌。当令牌数量不足的时候,请求将被阻塞进入等待状态或者直接返回失败。RateLimiter常用于限制访问资源的速率。

RateLimiter使用示例

下面是一个RateLimiter的简单使用示例:

代码语言:javascript
复制
public class RateLimiterTest {
    // 1秒钟产生0.5张令牌
    private final static RateLimiter limiter = RateLimiter.create(0.5);

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(5);
        IntStream.range(0, 5).forEach(i -> service.submit(RateLimiterTest::testLimiter));
        service.shutdown();
    }

    private static void testLimiter() {
        System.out.println(Thread.currentThread() + " waiting " + limiter.acquire());
    }
}

我们定义了一个RateLimiter实例,每秒钟产生0.5张令牌,即每2秒钟产生1张令牌。testLimiter方法中通过limiter.acquire()方法获取令牌(不带参数时默认获取1张令牌)。Executors.newFixedThreadPool(5)生成五个线程,并发调用testLimiter方法,执行代码,控制台输出如下所示:

代码语言:javascript
复制
Thread[pool-1-thread-1,5,main] waiting 0.0
Thread[pool-1-thread-5,5,main] waiting 1.908947
Thread[pool-1-thread-4,5,main] waiting 3.908935
Thread[pool-1-thread-3,5,main] waiting 5.908919
Thread[pool-1-thread-2,5,main] waiting 7.908808

可以看到每个线程调用时间相隔大约为2秒钟。可能你会问,为什么第一个线程没有等待2秒,直接就获取到了令牌然后执行了呢?

Guava RateLimiter允许某次请求获取超出剩余令牌数的令牌,但是下一次请求将为此付出代价,一直等到令牌亏空补上。再来看一个RateLimiter的例子:

代码语言:javascript
复制
public class RateLimiterTest {
    public static void main(String[] args) {
        RateLimiter limiter = RateLimiter.create(1);
        System.out.println(limiter.acquire(4));
        System.out.println(limiter.acquire(3));
        System.out.println(limiter.acquire(2));
        System.out.println(limiter.acquire(1));
    }
}

程序输出如下:

代码语言:javascript
复制
0.0
3.996602
2.997448
2.000229

上面例子钟,一秒钟产生一张令牌,第一次请求直接取出4张令牌,所以第二次请求需要等待4/1秒才能取到令牌。经过大约4秒后,第二次请求直接取出3张令牌,所以第三次请求需要等待3/1秒后才能取到令牌,依此类推。

设置超时时间

我们可以设置等待令牌的超时时间,如果等待令牌的时间大于超时时间,将直接返回false,不再等待:

代码语言:javascript
复制
public class RateLimiterTest {
    public static void main(String[] args) {
        RateLimiter limiter = RateLimiter.create(1);
        System.out.println(limiter.acquire(3));
        System.out.println(limiter.tryAcquire(1, 2, TimeUnit.SECONDS));
    }
}

上面例子limiter.tryAcquire设置了超时时间为2秒,由于第一次请求一次性获取了3张令牌,所以这里需要等待大约3秒钟,超出了2秒的超时时间,所以limiter.tryAcquire不会等待3秒,而是直接返回false。

每天

进步一点点

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术从心 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 来源:https://mrbird.cc/Guava-RateLimiter.html
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档