RateLimiter { public boolean tryAcquire() { if (maximumRequests <= 0) { return false; } Instant now = Instant.now(); synchronized (requests) { if (requests.size() < maximumRequests) { requests.push(now); return true; } Instant oldest = requests.getLast(); if (Duration.between(oldest, now).compareTo(expireDuration) >= 0) { requests.removeLast(); requests.push(now); return true; } } return false; } RateLimiter(Duration expireDuration, int maximumRequests); boolean tryAcquire(); Duration getExpireDuration(); int getMaximumRequests();  }
@Test public void testMaxSize() { limiter = new RateLimiter(Duration.ofMinutes(2), 3); for (int i = 0; i < 3; i++) { assertThat(limiter.tryAcquire(), is(true)); } assertThat(limiter.tryAcquire(), is(false)); }
@Test public void testExpiring() throws InterruptedException { limiter = new RateLimiter(Duration.ofSeconds(1), 3); for (int i = 0; i < 3; i++) { assertThat(limiter.tryAcquire(), is(true)); } assertThat(limiter.tryAcquire(), is(false)); TimeUnit.SECONDS.sleep(1); assertThat(limiter.tryAcquire(), is(true)); }
@Test public void testNoRequests() { limiter = new RateLimiter(Duration.ofMinutes(2), 0); assertThat(limiter.tryAcquire(), is(false)); limiter = new RateLimiter(Duration.ofMinutes(2), -50); assertThat(limiter.tryAcquire(), is(false)); }