Trying to implement a simple, thread-safe LRU cache that's meant for "read mostly" use.
Collections.sychronizedMap()
Clean, simple, not much else to say.
public class LRUConcurrentCache<K,V> {
private final Map<K,V> cache;
private final int maxEntries;
public LRUConcurrentCache(
int maxEntries
){
this.maxEntries = maxEntries;
this.cache = Collections.synchronizedMap(
new LinkedHashMap<K,V>(this.maxEntries, 0.75F, true){
private static final long serialVersionUID = -1236481390177598762L;
@Override
protected boolean removeEldestEntry(Map.Entry<K,V> eldest){
return size() > maxEntries;
}
});
}
public void put(K key, V value){
cache.put(key, value);
}
public V get(K key){
return cache.get(key);
}
ReadWriteLock
Seems like overkill, and frankly, I believe get()
should use writeLock()
, not readLock()
since LinkedHashMap.get()
records access by manipulating entries.
public class LRUConcurrentCache<K,V> {
private final Map<K,V> cache;
private final int maxEntries;
private final ReadWriteLock readWriteLock;
private final Lock readLock;
private final Lock writeLock;
public LRUConcurrentCache(
int maxEntries
){
this.maxEntries = maxEntries;
this.cache =
new LinkedHashMap<K,V>(this.maxEntries, 0.75F, true){
@Override
protected boolean removeEldestEntry(Map.Entry<K,V> eldest){
return size() > maxEntries;
}
};
this.readWriteLock = new ReentrantReadWriteLock(true);
this.readLock = readWriteLock.readLock();
this.writeLock = readWriteLock.writeLock();
}
public void put(K key, V value){
writeLock.lock();
try{
cache.put(key, value);
}finally{
writeLock.unlock();
}
}
public V get(K key){
//should use writeLock.lock()
readLock.lock();
try{
return cache.get(key);
}finally{
//should be writeLock()
readLock.unlock();
}
}
Thoughts?