CachedGauge implements Gauge<T> { @Override public T getValue() { T currentValue = this.value.get(); if (shouldLoad() || currentValue == null) { T newValue = loadValue(); if (!this.value.compareAndSet(currentValue, newValue)) { return this.value.get(); } return newValue; } return currentValue; } protected  CachedGauge(long timeout, TimeUnit timeoutUnit); protected  CachedGauge(Clock clock, long timeout, TimeUnit timeoutUnit); @Override T getValue();  }
@Test public void cachesTheValueForTheGivenPeriod() { assertThat(gauge.getValue()) .isEqualTo(1); assertThat(gauge.getValue()) .isEqualTo(1); }
@Test public void reloadsTheCachedValueAfterTheGivenPeriod() throws Exception { assertThat(gauge.getValue()) .isEqualTo(1); Thread.sleep(150); assertThat(gauge.getValue()) .isEqualTo(2); assertThat(gauge.getValue()) .isEqualTo(2); }
@Test public void multipleThreadAccessReturnsConsistentResults() throws Exception { List<Future<Boolean>> futures = new ArrayList<>(THREAD_COUNT); for (int i = 0; i < THREAD_COUNT; i++) { Future<Boolean> future = executor.submit(() -> { long startTime = System.currentTimeMillis(); int lastValue = 0; do { Integer newValue = shortTimeoutGauge.getValue(); if (newValue == null) { LOGGER.warn("Cached gauge returned null value"); return false; } if (newValue < lastValue) { LOGGER.error("Cached gauge returned stale value, last: {}, new: {}", lastValue, newValue); return false; } lastValue = newValue; } while (System.currentTimeMillis() - startTime <= RUNNING_TIME_MILLIS); return true; }); futures.add(future); } for (int i = 0; i < futures.size(); i++) { assertTrue("Future " + i + " failed", futures.get(i).get()); } executor.shutdown(); }