only iterates over elements when at least one element can be evicted
This commit is contained in:
@@ -98,8 +98,8 @@ public class HotEntryCache<K, V> {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void touch(final Clock clock) {
|
public void touch(final Instant instant) {
|
||||||
lastAccessed = Instant.now(clock);
|
lastAccessed = instant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +114,8 @@ public class HotEntryCache<K, V> {
|
|||||||
|
|
||||||
private Clock clock;
|
private Clock clock;
|
||||||
|
|
||||||
|
private Instant nextEviction = Instant.MAX;
|
||||||
|
|
||||||
HotEntryCache(final Duration timeToLive, final Clock clock, final long delayForEvictionThread,
|
HotEntryCache(final Duration timeToLive, final Clock clock, final long delayForEvictionThread,
|
||||||
final TimeUnit timeUnit) {
|
final TimeUnit timeUnit) {
|
||||||
this.timeToLive = timeToLive;
|
this.timeToLive = timeToLive;
|
||||||
@@ -131,12 +133,13 @@ public class HotEntryCache<K, V> {
|
|||||||
|
|
||||||
public V get(final K key) {
|
public V get(final K key) {
|
||||||
final Entry<V> entry = cache.computeIfPresent(key, (k, e) -> {
|
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());
|
handleEvent(EventType.EVICTED, k, e.getValue());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.touch(clock);
|
touch(e);
|
||||||
return e;
|
return e;
|
||||||
});
|
});
|
||||||
return entry != null ? entry.getValue() : null;
|
return entry != null ? entry.getValue() : null;
|
||||||
@@ -147,7 +150,9 @@ public class HotEntryCache<K, V> {
|
|||||||
final AtomicReference<Entry<V>> oldValue = new AtomicReference<>();
|
final AtomicReference<Entry<V>> oldValue = new AtomicReference<>();
|
||||||
cache.compute(key, (k, v) -> {
|
cache.compute(key, (k, v) -> {
|
||||||
oldValue.set(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;
|
return oldValue.get() != null ? oldValue.get().getValue() : null;
|
||||||
}
|
}
|
||||||
@@ -172,9 +177,8 @@ public class HotEntryCache<K, V> {
|
|||||||
return new Entry<>(value, clock);
|
return new Entry<>(value, clock);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (entry != null) {
|
touch(entry);
|
||||||
entry.touch(clock);
|
|
||||||
}
|
|
||||||
return entry != null ? entry.getValue() : null;
|
return entry != null ? entry.getValue() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,26 +201,37 @@ public class HotEntryCache<K, V> {
|
|||||||
|
|
||||||
public void forEach(final Consumer<V> consumer) {
|
public void forEach(final Consumer<V> consumer) {
|
||||||
cache.forEachValue(Long.MAX_VALUE, entry -> {
|
cache.forEachValue(Long.MAX_VALUE, entry -> {
|
||||||
entry.touch(clock);
|
touch(entry);
|
||||||
consumer.accept(entry.getValue());
|
consumer.accept(entry.getValue());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void evict() {
|
private void evict() {
|
||||||
for (final K key : cache.keySet()) {
|
final Instant now = Instant.now(clock);
|
||||||
|
if (nextEviction.isBefore(now)) {
|
||||||
|
|
||||||
cache.computeIfPresent(key, (k, e) -> {
|
for (final K key : cache.keySet()) {
|
||||||
if (isExpired(e)) {
|
cache.computeIfPresent(key, (k, e) -> {
|
||||||
handleEvent(EventType.EVICTED, k, e.getValue());
|
if (isExpired(e, now)) {
|
||||||
return null;
|
handleEvent(EventType.EVICTED, k, e.getValue());
|
||||||
}
|
return null;
|
||||||
return e;
|
}
|
||||||
});
|
return e;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExpired(final Entry<V> entry) {
|
private void touch(final Entry<V> entry) {
|
||||||
return entry.getLastAccessed().plus(timeToLive).isBefore(Instant.now(clock));
|
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) {
|
private void handleEvent(final EventType eventType, final K key, final V value) {
|
||||||
@@ -227,5 +242,4 @@ public class HotEntryCache<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user