only iterates over elements when at least one element can be evicted

This commit is contained in:
2018-11-23 06:34:41 +01:00
parent f78f69328b
commit 64771417e4

View File

@@ -98,8 +98,8 @@ public class HotEntryCache<K, V> {
return value;
}
public void touch(final Clock clock) {
lastAccessed = Instant.now(clock);
public void touch(final Instant instant) {
lastAccessed = instant;
}
}
@@ -114,6 +114,8 @@ public class HotEntryCache<K, V> {
private Clock clock;
private Instant nextEviction = Instant.MAX;
HotEntryCache(final Duration timeToLive, final Clock clock, final long delayForEvictionThread,
final TimeUnit timeUnit) {
this.timeToLive = timeToLive;
@@ -131,12 +133,13 @@ public class HotEntryCache<K, V> {
public V get(final K key) {
final Entry<V> entry = cache.computeIfPresent(key, (k, e) -> {
if (isExpired(e)) {
final Instant now = Instant.now(clock);
if (isExpired(e, now)) {
handleEvent(EventType.EVICTED, k, e.getValue());
return null;
}
e.touch(clock);
touch(e);
return e;
});
return entry != null ? entry.getValue() : null;
@@ -147,7 +150,9 @@ public class HotEntryCache<K, V> {
final AtomicReference<Entry<V>> oldValue = new AtomicReference<>();
cache.compute(key, (k, v) -> {
oldValue.set(v);
return new Entry<>(value, clock);
final Entry<V> newEntry = new Entry<>(value, clock);
touch(newEntry);
return newEntry;
});
return oldValue.get() != null ? oldValue.get().getValue() : null;
}
@@ -172,9 +177,8 @@ public class HotEntryCache<K, V> {
return new Entry<>(value, clock);
});
if (entry != null) {
entry.touch(clock);
}
touch(entry);
return entry != null ? entry.getValue() : null;
}
@@ -197,16 +201,18 @@ public class HotEntryCache<K, V> {
public void forEach(final Consumer<V> consumer) {
cache.forEachValue(Long.MAX_VALUE, entry -> {
entry.touch(clock);
touch(entry);
consumer.accept(entry.getValue());
});
}
private void evict() {
for (final K key : cache.keySet()) {
final Instant now = Instant.now(clock);
if (nextEviction.isBefore(now)) {
for (final K key : cache.keySet()) {
cache.computeIfPresent(key, (k, e) -> {
if (isExpired(e)) {
if (isExpired(e, now)) {
handleEvent(EventType.EVICTED, k, e.getValue());
return null;
}
@@ -214,9 +220,18 @@ public class HotEntryCache<K, V> {
});
}
}
}
private boolean isExpired(final Entry<V> entry) {
return entry.getLastAccessed().plus(timeToLive).isBefore(Instant.now(clock));
private void touch(final Entry<V> entry) {
if (entry != null) {
final Instant now = Instant.now(clock);
entry.touch(now);
nextEviction = now.plus(timeToLive);
}
}
private boolean isExpired(final Entry<V> entry, final Instant now) {
return entry.getLastAccessed().plus(timeToLive).isBefore(now);
}
private void handleEvent(final EventType eventType, final K key, final V value) {
@@ -227,5 +242,4 @@ public class HotEntryCache<K, V> {
}
}
}
}