apply new code formatter and save action

This commit is contained in:
2019-11-24 10:20:43 +01:00
parent 5ea82c6a4c
commit 06b379494f
184 changed files with 13455 additions and 13489 deletions

View File

@@ -26,380 +26,380 @@ import org.testng.annotations.Test;
@Test
public class HotEntryCacheTest {
static {
Configurator.setRootLevel(Level.TRACE);
}
static {
Configurator.setRootLevel(Level.TRACE);
}
private static final Logger LOGGER = LoggerFactory.getLogger(HotEntryCacheTest.class);
private static final Logger LOGGER = LoggerFactory.getLogger(HotEntryCacheTest.class);
private int cacheId = 0;
private int cacheId = 0;
@Test(invocationCount = 1)
public void testRemovalListenerCalledOnExpire() throws InterruptedException {
@Test(invocationCount = 1)
public void testRemovalListenerCalledOnExpire() throws InterruptedException {
LOGGER.info("");
LOGGER.info("");
LOGGER.info("start: testRemovalListenerCalledOnExpire");
LOGGER.info("");
LOGGER.info("");
LOGGER.info("start: testRemovalListenerCalledOnExpire");
final long originalMinSleepPeriod = HotEntryCache.getMinSleepPeriod();
final long originalMaxSleepPeriod = HotEntryCache.getMaxSleepPeriod();
try {
final String key = "key";
final String value = "value";
final CountDownLatch latch = new CountDownLatch(1);
final long originalMinSleepPeriod = HotEntryCache.getMinSleepPeriod();
final long originalMaxSleepPeriod = HotEntryCache.getMaxSleepPeriod();
try {
final String key = "key";
final String value = "value";
final CountDownLatch latch = new CountDownLatch(1);
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofMillis(1), 10,
"cache-" + ++cacheId);
HotEntryCache.setMinSleepPeriod(1);
HotEntryCache.setMaxSleepPeriod(2);
cache.addListener((k, v) -> {
Assert.assertEquals(k, key);
Assert.assertEquals(v, value);
latch.countDown();
});
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofMillis(1), 10,
"cache-" + ++cacheId);
HotEntryCache.setMinSleepPeriod(1);
HotEntryCache.setMaxSleepPeriod(2);
cache.addListener((k, v) -> {
Assert.assertEquals(k, key);
Assert.assertEquals(v, value);
latch.countDown();
});
cache.put(key, value);
final boolean listenerCalled = latch.await(100, TimeUnit.MILLISECONDS);
Assert.assertTrue(listenerCalled, "removal listener called");
} finally {
HotEntryCache.setMinSleepPeriod(originalMinSleepPeriod);
HotEntryCache.setMaxSleepPeriod(originalMaxSleepPeriod);
}
}
cache.put(key, value);
final boolean listenerCalled = latch.await(100, TimeUnit.MILLISECONDS);
Assert.assertTrue(listenerCalled, "removal listener called");
} finally {
HotEntryCache.setMinSleepPeriod(originalMinSleepPeriod);
HotEntryCache.setMaxSleepPeriod(originalMaxSleepPeriod);
}
}
public void testPutAndGet() throws InterruptedException, ExecutionException, TimeoutException {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
public void testPutAndGet() throws InterruptedException, ExecutionException, TimeoutException {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String replacedNull = cache.put("key", "value1");
Assert.assertEquals(replacedNull, null);
final String replacedNull = cache.put("key", "value1");
Assert.assertEquals(replacedNull, null);
final String cachedValue1 = cache.get("key");
Assert.assertEquals(cachedValue1, "value1");
final String cachedValue1 = cache.get("key");
Assert.assertEquals(cachedValue1, "value1");
final String replacedValue1 = cache.put("key", "value2");
Assert.assertEquals(replacedValue1, "value1");
final String replacedValue1 = cache.put("key", "value2");
Assert.assertEquals(replacedValue1, "value1");
final String cachedValue2 = cache.get("key");
Assert.assertEquals(cachedValue2, "value2");
}
final String cachedValue2 = cache.get("key");
Assert.assertEquals(cachedValue2, "value2");
}
public void testPutTouches() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
public void testPutTouches() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
cache.put("key", "value1");
cache.put("key", "value1");
clock.plusSeconds(2);
cache.updateTime();
clock.plusSeconds(2);
cache.updateTime();
cache.put("key", "value2");
cache.put("key", "value2");
clock.plus(timeToLive.minusSeconds(1));
cache.triggerEvictionAndWait();
// at this point the entry would have been evicted it it was not touched by the
// second put.
clock.plus(timeToLive.minusSeconds(1));
cache.triggerEvictionAndWait();
// at this point the entry would have been evicted it it was not touched by the
// second put.
final String cachedValue2 = cache.get("key");
Assert.assertEquals(cachedValue2, "value2");
final String cachedValue2 = cache.get("key");
Assert.assertEquals(cachedValue2, "value2");
clock.plus(timeToLive.plusSeconds(1));
// time elapsed since the last put: timeToLive +1s
cache.triggerEvictionAndWait();
clock.plus(timeToLive.plusSeconds(1));
// time elapsed since the last put: timeToLive +1s
cache.triggerEvictionAndWait();
final String cachedValue1_evicted = cache.get("key");
Assert.assertEquals(cachedValue1_evicted, null);
}
final String cachedValue1_evicted = cache.get("key");
Assert.assertEquals(cachedValue1_evicted, null);
}
public void testGetTouches() throws Exception {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
public void testGetTouches() throws Exception {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
cache.put("key", "value1");
cache.put("key", "value1");
// skip forward in time, but do not yet trigger eviction
clock.plus(timeToLive.plusMillis(1));
cache.updateTime();
// skip forward in time, but do not yet trigger eviction
clock.plus(timeToLive.plusMillis(1));
cache.updateTime();
cache.get("key"); // will touch the entry
cache.get("key"); // will touch the entry
cache.triggerEvictionAndWait(); // if get didn't touch, then this will evict the entry
cache.triggerEvictionAndWait(); // if get didn't touch, then this will evict the entry
final String cachedValue1 = cache.get("key");
Assert.assertEquals(cachedValue1, "value1");
}
final String cachedValue1 = cache.get("key");
Assert.assertEquals(cachedValue1, "value1");
}
public void testEvictionByBackgroundThread() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
public void testEvictionByBackgroundThread() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
final CompletableFuture<String> evictionEventFuture = new CompletableFuture<>();
cache.addListener((key, value) -> {
evictionEventFuture.complete(value);
});
final CompletableFuture<String> evictionEventFuture = new CompletableFuture<>();
cache.addListener((key, value) -> {
evictionEventFuture.complete(value);
});
cache.put("key", "value1");
cache.put("key", "value1");
clock.plus(timeToLive.minusSeconds(1));
cache.updateTime();
clock.plus(timeToLive.minusSeconds(1));
cache.updateTime();
cache.put("key2", "value2");
clock.plus(Duration.ofSeconds(1).plusMillis(1));
cache.triggerEvictionAndWait();
cache.put("key2", "value2");
clock.plus(Duration.ofSeconds(1).plusMillis(1));
cache.triggerEvictionAndWait();
final String evictedValue1 = evictionEventFuture.get(5, TimeUnit.MINUTES); // enough time for debugging
Assert.assertEquals(evictedValue1, "value1");
}
final String evictedValue1 = evictionEventFuture.get(5, TimeUnit.MINUTES); // enough time for debugging
Assert.assertEquals(evictedValue1, "value1");
}
public void testRemove() throws InterruptedException, ExecutionException, TimeoutException {
LOGGER.info("");
LOGGER.info("");
LOGGER.info("start: testRemove");
public void testRemove() throws InterruptedException, ExecutionException, TimeoutException {
LOGGER.info("");
LOGGER.info("");
LOGGER.info("start: testRemove");
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final List<String> removedValues = new ArrayList<>();
cache.addListener((key, value) -> removedValues.add(value));
final List<String> removedValues = new ArrayList<>();
cache.addListener((key, value) -> removedValues.add(value));
cache.put("key", "value1");
cache.put("key", "value1");
final String removedValue = cache.remove("key");
Assert.assertEquals(removedValue, "value1");
final String removedValue = cache.remove("key");
Assert.assertEquals(removedValue, "value1");
Assert.assertEquals(removedValues, Arrays.asList("value1"));
Assert.assertEquals(removedValues, Arrays.asList("value1"));
Assert.assertEquals(cache.get("key"), null);
}
Assert.assertEquals(cache.get("key"), null);
}
public void testClear() throws InterruptedException, ExecutionException, TimeoutException {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
public void testClear() throws InterruptedException, ExecutionException, TimeoutException {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final List<String> removedValues = new ArrayList<>();
cache.addListener((key, value) -> removedValues.add(value));
final List<String> removedValues = new ArrayList<>();
cache.addListener((key, value) -> removedValues.add(value));
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.clear();
cache.clear();
Assert.assertEquals(cache.get("key1"), null);
Assert.assertEquals(cache.get("key2"), null);
Assert.assertEquals(cache.get("key1"), null);
Assert.assertEquals(cache.get("key2"), null);
Assert.assertEquals(removedValues, Arrays.asList("value1", "value2"));
}
Assert.assertEquals(removedValues, Arrays.asList("value1", "value2"));
}
public void testForEachTouches() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
public void testForEachTouches() throws InterruptedException, ExecutionException, TimeoutException {
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final Duration timeToLive = Duration.ofSeconds(10);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10, clock);
final CompletableFuture<String> evictionEventFuture = new CompletableFuture<>();
cache.addListener((key, value) -> {
evictionEventFuture.complete(value);
});
final CompletableFuture<String> evictionEventFuture = new CompletableFuture<>();
cache.addListener((key, value) -> {
evictionEventFuture.complete(value);
});
// add value
cache.put("key", "value1");
// add value
cache.put("key", "value1");
// seek, so that it is almost evicted
clock.plus(timeToLive.minusMillis(1));
cache.updateTime();
// seek, so that it is almost evicted
clock.plus(timeToLive.minusMillis(1));
cache.updateTime();
// the for each should touch the entries
cache.forEach(s -> {
/* no-op */});
// the for each should touch the entries
cache.forEach(s -> {
/* no-op */});
// seek again
clock.plus(timeToLive.minusMillis(1));
cache.triggerEvictionAndWait();
// seek again
clock.plus(timeToLive.minusMillis(1));
cache.triggerEvictionAndWait();
// if the touch didn't happen, then the value is now evicted
Assert.assertEquals(evictionEventFuture.isDone(), false);
// if the touch didn't happen, then the value is now evicted
Assert.assertEquals(evictionEventFuture.isDone(), false);
// seek again, so that the entry will get evicted
clock.plus(timeToLive.minusMillis(1));
cache.triggerEvictionAndWait();
// seek again, so that the entry will get evicted
clock.plus(timeToLive.minusMillis(1));
cache.triggerEvictionAndWait();
Assert.assertEquals(cache.get("key"), null);
}
/**
* Checks that
* {@link HotEntryCache#putIfAbsent(Object, java.util.function.Function)
* putIfAbsent} is atomic by calling
* {@link HotEntryCache#putIfAbsent(Object, java.util.function.Function)
* putIfAbsent} in two threads and asserting that the supplier was only called
* once.
*
* @throws Exception
*/
public void testPutIfAbsentIsAtomic() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final ExecutorService pool = Executors.newCachedThreadPool();
try {
final CountDownLatch latch = new CountDownLatch(1);
final String key = "key";
final String valueA = "A";
final String valueB = "B";
pool.submit(() -> {
cache.putIfAbsent(key, k -> {
latch.countDown();
sleep(TimeUnit.MILLISECONDS, 20);
return valueA;
});
return null;
});
pool.submit(() -> {
waitFor(latch);
cache.putIfAbsent(key, k -> valueB);
return null;
});
pool.shutdown();
pool.awaitTermination(1, TimeUnit.MINUTES);
final String actual = cache.get(key);
Assert.assertEquals(actual, valueA);
} finally {
pool.shutdownNow();
}
}
public void testPutIfAbsentReturnsExistingValue() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String key = "key";
final String valueA = "A";
final String valueB = "B";
cache.put(key, valueA);
final String returnedByPutIfAbsent = cache.putIfAbsent(key, k -> valueB);
Assert.assertEquals(returnedByPutIfAbsent, valueA);
final String actualInCache = cache.get(key);
Assert.assertEquals(actualInCache, valueA);
}
public void testPutIfAbsentDoesNotAddNull() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String key = "key";
final String returnedByPutIfAbsent = cache.putIfAbsent(key, k -> null);
Assert.assertNull(returnedByPutIfAbsent, null);
final String actualInCache = cache.get(key);
Assert.assertEquals(actualInCache, null);
}
public void testMaxSizeIsRespected() {
final int maxSize = 10;
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofHours(1), maxSize, clock);
final Set<String> removedKeys = new LinkedHashSet<>();
cache.addListener((key, value) -> removedKeys.add(key));
// fill the cache
int count = 0;
for (count = 0; count < maxSize; count++) {
cache.put("key" + count, "value" + count);
clock.plus(2L, ChronoUnit.MILLIS);
cache.updateTime();
}
Assert.assertEquals(cache.size(), maxSize, "cache is full");
Assert.assertEquals(removedKeys, List.of(), "removed keys at point A");
// add an item to a full cache -> the oldest 20% of the entries will be evicted
// before the new entry is added
cache.put("key" + count, "value" + count);
clock.plus(2L, ChronoUnit.MILLIS);
cache.updateTime();
count++;
Assert.assertEquals(cache.size(), maxSize - 1, "cache was full, 20% (2 items) were removed and one added");
Assert.assertEquals(removedKeys, Set.of("key0", "key1"), "removed keys at point B");
}
public void testEvictionDueToSizeLimitDoesNotRemoveMoreThan20Percent() {
final int maxSize = 10;
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofHours(1), maxSize, clock);
final Set<String> removedKeys = new LinkedHashSet<>();
cache.addListener((key, value) -> removedKeys.add(key));
// fill the cache
int count = 0;
for (count = 0; count < maxSize; count++) {
// all entries get the same eviction time due to the fixed clock
cache.put("key" + count, "value" + count);
}
Assert.assertEquals(cache.size(), maxSize, "cache is full");
Assert.assertEquals(removedKeys, List.of(), "removed keys at point A");
// add an item to a full cache -> the oldest 20% of the entries will be evicted
// before the new entry is added
cache.put("key" + count, "value" + count);
count++;
Assert.assertEquals(cache.size(), maxSize - 1, "cache was full, 20% (2 items) were removed and one added");
Assert.assertEquals(removedKeys.size(), (int) (maxSize * 0.2), "number of removed keys at point B");
}
private void sleep(final TimeUnit timeUnit, final long timeout) {
try {
timeUnit.sleep(timeout);
} catch (final InterruptedException e) {
throw new IllegalStateException(e);
}
}
private void waitFor(final CountDownLatch latch) {
try {
latch.await(1, TimeUnit.MINUTES);
} catch (final InterruptedException e) {
throw new IllegalStateException(e);
}
}
public static void main(final String[] args) throws InterruptedException {
Configurator.setRootLevel(Level.TRACE);
final Duration timeToLive = Duration.ofSeconds(1);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10);
cache.addListener((key, value) -> {
System.out.println(Instant.now() + " evicting: " + key + " -> " + value);
});
cache.put("key", "value that is touched");
for (int i = 0; i < 20; i++) {
System.out.println(Instant.now() + " putting value" + i);
cache.put("key" + i, "value" + i);
cache.put("key", "value that is touched" + i);
TimeUnit.MILLISECONDS.sleep(450);
}
for (int i = 20; i < 23; i++) {
System.out.println(Instant.now() + " putting value" + i);
cache.put("key" + i, "value" + i);
TimeUnit.MILLISECONDS.sleep(Duration.ofSeconds(5).plusMillis(10).toMillis());
}
TimeUnit.MILLISECONDS.sleep(Duration.ofSeconds(5).plusMillis(10).toMillis());
for (int i = 23; i < 27; i++) {
System.out.println(Instant.now() + " putting value" + i);
cache.put("key" + i, "value" + i);
TimeUnit.MILLISECONDS.sleep(Duration.ofSeconds(5).plusMillis(10).toMillis());
}
TimeUnit.SECONDS.sleep(300);
}
Assert.assertEquals(cache.get("key"), null);
}
/**
* Checks that
* {@link HotEntryCache#putIfAbsent(Object, java.util.function.Function)
* putIfAbsent} is atomic by calling
* {@link HotEntryCache#putIfAbsent(Object, java.util.function.Function)
* putIfAbsent} in two threads and asserting that the supplier was only called
* once.
*
* @throws Exception
*/
public void testPutIfAbsentIsAtomic() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final ExecutorService pool = Executors.newCachedThreadPool();
try {
final CountDownLatch latch = new CountDownLatch(1);
final String key = "key";
final String valueA = "A";
final String valueB = "B";
pool.submit(() -> {
cache.putIfAbsent(key, k -> {
latch.countDown();
sleep(TimeUnit.MILLISECONDS, 20);
return valueA;
});
return null;
});
pool.submit(() -> {
waitFor(latch);
cache.putIfAbsent(key, k -> valueB);
return null;
});
pool.shutdown();
pool.awaitTermination(1, TimeUnit.MINUTES);
final String actual = cache.get(key);
Assert.assertEquals(actual, valueA);
} finally {
pool.shutdownNow();
}
}
public void testPutIfAbsentReturnsExistingValue() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String key = "key";
final String valueA = "A";
final String valueB = "B";
cache.put(key, valueA);
final String returnedByPutIfAbsent = cache.putIfAbsent(key, k -> valueB);
Assert.assertEquals(returnedByPutIfAbsent, valueA);
final String actualInCache = cache.get(key);
Assert.assertEquals(actualInCache, valueA);
}
public void testPutIfAbsentDoesNotAddNull() throws Exception {
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofSeconds(10), 10);
final String key = "key";
final String returnedByPutIfAbsent = cache.putIfAbsent(key, k -> null);
Assert.assertNull(returnedByPutIfAbsent, null);
final String actualInCache = cache.get(key);
Assert.assertEquals(actualInCache, null);
}
public void testMaxSizeIsRespected() {
final int maxSize = 10;
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofHours(1), maxSize, clock);
final Set<String> removedKeys = new LinkedHashSet<>();
cache.addListener((key, value) -> removedKeys.add(key));
// fill the cache
int count = 0;
for (count = 0; count < maxSize; count++) {
cache.put("key" + count, "value" + count);
clock.plus(2L, ChronoUnit.MILLIS);
cache.updateTime();
}
Assert.assertEquals(cache.size(), maxSize, "cache is full");
Assert.assertEquals(removedKeys, List.of(), "removed keys at point A");
// add an item to a full cache -> the oldest 20% of the entries will be evicted
// before the new entry is added
cache.put("key" + count, "value" + count);
clock.plus(2L, ChronoUnit.MILLIS);
cache.updateTime();
count++;
Assert.assertEquals(cache.size(), maxSize - 1, "cache was full, 20% (2 items) were removed and one added");
Assert.assertEquals(removedKeys, Set.of("key0", "key1"), "removed keys at point B");
}
public void testEvictionDueToSizeLimitDoesNotRemoveMoreThan20Percent() {
final int maxSize = 10;
final ModifiableFixedTimeClock clock = new ModifiableFixedTimeClock();
final HotEntryCache<String, String> cache = new HotEntryCache<>(Duration.ofHours(1), maxSize, clock);
final Set<String> removedKeys = new LinkedHashSet<>();
cache.addListener((key, value) -> removedKeys.add(key));
// fill the cache
int count = 0;
for (count = 0; count < maxSize; count++) {
// all entries get the same eviction time due to the fixed clock
cache.put("key" + count, "value" + count);
}
Assert.assertEquals(cache.size(), maxSize, "cache is full");
Assert.assertEquals(removedKeys, List.of(), "removed keys at point A");
// add an item to a full cache -> the oldest 20% of the entries will be evicted
// before the new entry is added
cache.put("key" + count, "value" + count);
count++;
Assert.assertEquals(cache.size(), maxSize - 1, "cache was full, 20% (2 items) were removed and one added");
Assert.assertEquals(removedKeys.size(), (int) (maxSize * 0.2), "number of removed keys at point B");
}
private void sleep(final TimeUnit timeUnit, final long timeout) {
try {
timeUnit.sleep(timeout);
} catch (final InterruptedException e) {
throw new IllegalStateException(e);
}
}
private void waitFor(final CountDownLatch latch) {
try {
latch.await(1, TimeUnit.MINUTES);
} catch (final InterruptedException e) {
throw new IllegalStateException(e);
}
}
public static void main(final String[] args) throws InterruptedException {
Configurator.setRootLevel(Level.TRACE);
final Duration timeToLive = Duration.ofSeconds(1);
final HotEntryCache<String, String> cache = new HotEntryCache<>(timeToLive, 10);
cache.addListener((key, value) -> {
System.out.println(Instant.now() + " evicting: " + key + " -> " + value);
});
cache.put("key", "value that is touched");
for (int i = 0; i < 20; i++) {
System.out.println(Instant.now() + " putting value" + i);
cache.put("key" + i, "value" + i);
cache.put("key", "value that is touched" + i);
TimeUnit.MILLISECONDS.sleep(450);
}
for (int i = 20; i < 23; i++) {
System.out.println(Instant.now() + " putting value" + i);
cache.put("key" + i, "value" + i);
TimeUnit.MILLISECONDS.sleep(Duration.ofSeconds(5).plusMillis(10).toMillis());
}
TimeUnit.MILLISECONDS.sleep(Duration.ofSeconds(5).plusMillis(10).toMillis());
for (int i = 23; i < 27; i++) {
System.out.println(Instant.now() + " putting value" + i);
cache.put("key" + i, "value" + i);
TimeUnit.MILLISECONDS.sleep(Duration.ofSeconds(5).plusMillis(10).toMillis());
}
TimeUnit.SECONDS.sleep(300);
}
}

View File

@@ -12,87 +12,87 @@ import java.time.temporal.TemporalUnit;
* useful in tests, so that you can explicitly set the time.
*/
public class ModifiableFixedTimeClock extends Clock implements Serializable {
private static final long serialVersionUID = 1955332545617873736L;
private Instant instant;
private final ZoneId zone;
private static final long serialVersionUID = 1955332545617873736L;
private Instant instant;
private final ZoneId zone;
public ModifiableFixedTimeClock() {
this(Instant.now());
}
public ModifiableFixedTimeClock() {
this(Instant.now());
}
public ModifiableFixedTimeClock(final Instant fixedInstant) {
this(fixedInstant, ZoneId.systemDefault());
}
public ModifiableFixedTimeClock(final Instant fixedInstant) {
this(fixedInstant, ZoneId.systemDefault());
}
public ModifiableFixedTimeClock(final Instant fixedInstant, final ZoneId zone) {
this.instant = fixedInstant;
this.zone = zone;
}
public ModifiableFixedTimeClock(final Instant fixedInstant, final ZoneId zone) {
this.instant = fixedInstant;
this.zone = zone;
}
public void setTime(final Instant instant) {
this.instant = instant;
}
public void setTime(final Instant instant) {
this.instant = instant;
}
public void plus(final TemporalAmount amountToAdd) {
instant = instant.plus(amountToAdd);
}
public void plus(final TemporalAmount amountToAdd) {
instant = instant.plus(amountToAdd);
}
public void plus(final long amountToAdd, final TemporalUnit unit) {
instant = instant.plus(amountToAdd, unit);
}
public void plus(final long amountToAdd, final TemporalUnit unit) {
instant = instant.plus(amountToAdd, unit);
}
public void plusMillis(final long millisToAdd) {
instant = instant.plusMillis(millisToAdd);
}
public void plusMillis(final long millisToAdd) {
instant = instant.plusMillis(millisToAdd);
}
public void plusNanos(final long nanosToAdd) {
instant = instant.plusNanos(nanosToAdd);
}
public void plusNanos(final long nanosToAdd) {
instant = instant.plusNanos(nanosToAdd);
}
public void plusSeconds(final long secondsToAdd) {
instant = instant.plusSeconds(secondsToAdd);
}
public void plusSeconds(final long secondsToAdd) {
instant = instant.plusSeconds(secondsToAdd);
}
@Override
public ZoneId getZone() {
return zone;
}
@Override
public ZoneId getZone() {
return zone;
}
@Override
public Clock withZone(final ZoneId zone) {
if (zone.equals(this.zone)) {
return this;
}
return new ModifiableFixedTimeClock(instant, zone);
}
@Override
public Clock withZone(final ZoneId zone) {
if (zone.equals(this.zone)) {
return this;
}
return new ModifiableFixedTimeClock(instant, zone);
}
@Override
public long millis() {
return instant.toEpochMilli();
}
@Override
public long millis() {
return instant.toEpochMilli();
}
@Override
public Instant instant() {
return instant;
}
@Override
public Instant instant() {
return instant;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof ModifiableFixedTimeClock) {
final ModifiableFixedTimeClock other = (ModifiableFixedTimeClock) obj;
return instant.equals(other.instant) && zone.equals(other.zone);
}
return false;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof ModifiableFixedTimeClock) {
final ModifiableFixedTimeClock other = (ModifiableFixedTimeClock) obj;
return instant.equals(other.instant) && zone.equals(other.zone);
}
return false;
}
@Override
public int hashCode() {
return instant.hashCode() ^ zone.hashCode();
}
@Override
public int hashCode() {
return instant.hashCode() ^ zone.hashCode();
}
@Override
public String toString() {
return "FixedClock[" + instant + "," + zone + "]";
}
@Override
public String toString() {
return "FixedClock[" + instant + "," + zone + "]";
}
}