Google RateLimiter不适用于计数器

时间:2017-10-20 08:40:58

标签: java guava throttling

我有限制调用100 / s的情况。

我正在考虑使用Google Guava RateLimiter。我测试了这样: -

int cps = 100;
    RateLimiter limiter = RateLimiter.create(cps);
for(int i=0;i<200;i++) {
   limiter.acquire();
   System.out.print("\rNumber of records processed = " + i+1);
}

但是代码没有停在100条记录上,让1秒完成。我做错了吗?

2 个答案:

答案 0 :(得分:5)

RateLimiter工作正常。问题是您的输出是缓冲的,因为您每次都不会刷新它。通常,标准输出是行缓冲的。所以,如果你写了

System.out.println("Number of records processed = " + (i+1));

你会看到100暂停。但是,你有什么:

System.out.print(&#34; \ r \ n已处理的记录数量=&#34; + i + 1);

有两个问题。首先,&#34; \ r&#34;不被视为新线,不会引起潮红;因此整个输出都被缓冲并一次性打印到控制台。其次,你需要把(i + 1)括在括号中。你将i追加到字符串中,然后将1附加到结果字符串。

答案 1 :(得分:2)

除了@ DodgyCodeException关于输出刷新和连接+1的建议之外,让我们运行此代码以确保您了解RateLimiter的工作原理:

final double permitsPerSecond = 1;
RateLimiter limiter = RateLimiter.create(permitsPerSecond);
final Stopwatch stopwatch = Stopwatch.createStarted();
int i = 0;
for (; i < 2 * permitsPerSecond; i++) {
  limiter.acquire();
}
System.out.println("Elapsed = " + stopwatch.stop().elapsed(TimeUnit.MILLISECONDS) + "ms");
System.out.println("Number of records processed = " + i);

(请注意,我将尝试次数设置为permitsPerSecond次数的两倍。)当您将permitsPerSecond设置为1时,您会看到:

  

经过= 1001ms
  处理的记录数= 2

对于permitsPerSecond = 10;permitsPerSecond = 100;,它接近(在数学意义上)2s限制,因为第11或第101次尝试等待RateLimiter中设置的限制:

  

Elapsed = 1902ms
  处理的记录数= 20

  

Elapsed = 1991ms
  处理的记录数= 200