K
- The type of the keysV
- The type of the valuespublic class Cache<K,V>
extends java.lang.Object
Cache is a simple concurrent cache that supports time-based and weight-based evictions, with notifications for all evictions. The design goals for this cache were simplicity and read performance. This means that we are willing to accept reduced write performance in exchange for easy-to-understand code. Cache statistics for hits, misses and evictions are exposed.
The design of the cache is relatively simple. The cache is segmented into 256 segments which are backed by HashMaps. Each segment is protected by a re-entrant read/write lock. The read/write locks permit multiple concurrent readers without contention, and the segments gives us write throughput without impacting readers (so readers are blocked only if they are reading a segment that a writer is writing to).
The LRU functionality is backed by a single doubly-linked list chaining the entries in order of insertion. This LRU list is protected by a lock that serializes all writes to it. There are opportunities for improvements here if write throughput is a concern.
Evictions only occur after a mutation to the cache (meaning an entry promotion, a cache insertion, or a manual
invalidation) or an explicit call to refresh()
.
Modifier and Type | Class | Description |
---|---|---|
static class |
Cache.CacheStats |
Modifier and Type | Field | Description |
---|---|---|
static int |
NUMBER_OF_SEGMENTS |
Modifier and Type | Method | Description |
---|---|---|
V |
computeIfAbsent(K key,
CacheLoader<K,V> loader) |
If the specified key is not already associated with a value (or is mapped to null), attempts to compute its
value using the given mapping function and enters it into this map unless null.
|
int |
count() |
The number of entries in the cache.
|
V |
get(K key) |
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
|
void |
invalidate(K key) |
Invalidate the association for the specified key.
|
void |
invalidateAll() |
Invalidate all cache entries.
|
java.lang.Iterable<K> |
keys() |
An LRU sequencing of the keys in the cache that supports removal.
|
protected long |
now() |
The relative time used to track time-based evictions.
|
void |
put(K key,
V value) |
Associates the specified value with the specified key in this map.
|
void |
refresh() |
Force any outstanding size-based and time-based evictions to occur
|
Cache.CacheStats |
stats() |
The cache statistics tracking hits, misses and evictions.
|
java.lang.Iterable<V> |
values() |
An LRU sequencing of the values in the cache.
|
long |
weight() |
The weight of the entries in the cache.
|
public static final int NUMBER_OF_SEGMENTS
protected long now()
public V get(K key)
key
- the key whose associated value is to be returnedpublic V computeIfAbsent(K key, CacheLoader<K,V> loader) throws java.util.concurrent.ExecutionException
CacheLoader
implementations on the same key concurrently may result in only the first
loader function being called and the second will be returned the result provided by the first including any exceptions
thrown during the execution of the first.key
- the key whose associated value is to be returned or computed for if non-existentloader
- the function to compute a value given a keyjava.util.concurrent.ExecutionException
- thrown if loader throws an exception or returns a null valuepublic void put(K key, V value)
key
- key with which the specified value is to be associatedvalue
- value to be associated with the specified keypublic void invalidate(K key)
RemovalNotification.RemovalReason
INVALIDATED.key
- the key whose mapping is to be invalidated from the cachepublic void invalidateAll()
RemovalNotification.RemovalReason
INVALIDATED.public void refresh()
public int count()
public long weight()
public java.lang.Iterable<K> keys()
Iterator.remove()
. The result of iteration under any other mutation is
undefined.Iterable
over the keys in the cachepublic java.lang.Iterable<V> values()
Iterable
over the values in the cachepublic Cache.CacheStats stats()