链接地址:http://www.xx566.com/detail/164.html
上一篇,Guava库学习:学习Concurrency(八)Futures中,我们学习了Futures工具类用于操作Future实例,通过Futures,我们可以很简单的进行并发的编程,本篇我们继续Guava Concurrency的学习,Concurrency(九)RateLimiter,RateLimiter 类与Java api中的semaphore信号量比较类似,主要用于限制对资源并发访问的线程数,RateLimiter类限制线程访问的时间,这就意味着可以限制每 秒中线程访问资源的数量,接下来,我们开始Guava Concurrency RateLimiter的学习。
我们可以通过下面的方式创建RateLimiter实例,如下:
RateLimiter limiter = RateLimiter.create(4.0);
上面的代码中,我们通过RateLimiter类提供的静态create方法,传入一个double类型的参数4.0,这就意味着每秒不超过4个任务被提 交。当我们要限制线程访问的时间时,我们需要用到RateLimiter类,我们可以使用和JDK信号量相同的方式进行操作,向下面这样:
limiter.acquire(); executor.submit(new Callable<Object>() { @Override public Object call() throws Exception { return "Hello RateLimiter"; } });
在上面的代码中,我们调用了acquire方法,在获取允许访问资源的许可之前,线程会阻塞, 如果我们不希望当前线程阻塞,我们可以这样调用:
if(limiter.tryAcquire()){ //有资源访问的许可 System.out.println("someThing"); }else{ //没有资源访问的许可 System.out.println("anotherThing"); }
上面的例子中,我们调用了tryAcquire方法,判断是否拥有资源访问的许可, 如果没有许可的话,将立即执行anotherThing部分的代码。tryAcquire方法有另外重载的方法,我们可以设置特定的超时时间,具体的方法我们将在下面的介绍中说明。
翻开RateLimiter的源码,我们简单的整理一下其中的公共方法,如下:
create(double permitsPerSecond):创建具有指定稳定吞吐量的RateLimiter类,传入允许每秒提交的任务数量。
create(double permitsPerSecond, long warmupPeriod, TimeUnit unit):创建具有指定稳定吞吐量的RateLimiter类,传入允许每秒提交的任务数量和准备阶段的时间,在这段时间RateLimiter会有个缓冲,直到达到它的最大速率(只要有饱和的足够的请求)。
setRate(double permitsPerSecond):稳定的更新RateLimiter的速率,RateLimiter的构造方法中中设置permitsPerSecond参数,调用这个方法后,当前阻塞的线程不会被唤醒,因此它们不会观察到新的速率被设置。
getRate():返回RateLimiter被设置的稳定的速率值。
acquire():从这个ratelimiter获得一个许可,阻塞线程直到请求可以再授予许可。
acquire(int permits):获取传入数量的许可,阻塞线程直到请求可以再授予许可。
tryAcquire(long timeout, TimeUnit unit):判断是否可以在指定的时间内从ratelimiter获得一个许可,或者在超时期间内未获得许可的话,立即返回false。
tryAcquire(int permits):判断是否可以立即获取相应数量的许可。
tryAcquire():判断是否可以立即获取许可。
tryAcquire(int permits, long timeout, TimeUnit unit):判断是否可以在超时时间内获取相应数量的许可。
代码地址:http://git.oschina.net/realfighter/xx566-diary/blob/master/src/guava/RateLimiterTest.java