Google RateLimiter 不适用于计数器

Google RateLimiter not Working for counter

我有将调用限制为 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 秒完成。我做错了什么吗?

速率限制器工作正常。问题是你的输出被缓冲了,因为你不是每次都刷新它。通常,标准输出是行缓冲的。所以如果你写了

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

您会在 100 处看到暂停。但是,您拥有的是:

System.out.print("\r处理的记录数 = " + i+1);

有两个问题。首先,“\r”不作为换行,不会导致刷新;因此,整个输出都被缓冲并一次性打印到控制台。其次,您需要将 (i+1) 放在括号中。你所拥有的将 i 附加到字符串,然后将 1 附加到结果字符串。

除了@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 时,您会看到:

Elapsed = 1001ms
Number of records processed = 2

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

Elapsed = 1902ms
Number of records processed = 20

Elapsed = 1991ms
Number of records processed = 200