我正在写一个缓存实现-如果存储的项在存储中的时间超过5分钟,它就会过期。在这种情况下,应该从源刷新它,否则应该返回缓存的副本。
下面是我写的--它有没有设计上的缺陷?特别是get部分?
public class Cache<K,V> {
private final ConcurrentMap<K,TimedItem> store ;
private final long expiryInMilliSec ;
Cache(){
store = new ConcurrentHashMap<K, TimedItem>(16);
expiryInMilliSec = 5 * 60 * 1000; // 5 mins
}
Cache(int minsToExpire){
store = new ConcurrentHashMap<K, TimedItem>(16);
expiryInMilliSec = minsToExpire * 60 * 1000;
}
// Internal class to hold item and its 'Timestamp' together
private class TimedItem {
private long timeStored ;
private V item ;
TimedItem(V v) {
item = v;
timeStored = new Date().getTime();
}
long getTimeStored(){
return timeStored;
}
V getItem(){
return item;
}
public String toString(){
return item.toString();
}
}
// sync on the store object - its a way to ensure that it does not interfere
// with the get method's logic below
public void put(K key, V item){
synchronized(store){
store.putIfAbsent(key, new TimedItem(item));
}
}
// Lookup the item, check if its timestamp is earlier than current time
// allowing for the expiry duration
public V get(K key){
TimedItem ti = null;
K keyLocal = key;
boolean refreshRequired = false;
synchronized(store){
ti = store.get(keyLocal);
if(ti == null)
return null;
long currentTime = new Date().getTime();
if( (currentTime - ti.getTimeStored()) > expiryInMilliSec ){
store.remove(keyLocal);
refreshRequired = true;
}
}
// even though this is not a part of the sync block , this should not be a problem
// from a concurrency point of view
if(refreshRequired){
ti = store.putIfAbsent(keyLocal, new TimedItem(getItemFromSource(keyLocal)) );
}
return ti.getItem();
}
private V getItemFromSource(K key){
// implement logic for refreshing item from source
return null ;
}
public String toString(){
return store.toString();
}}
发布于 2011-07-30 06:47:10
假设您正在尝试手动同步,并且(在猜测中)您似乎没有对其进行非常彻底的测试,我会说有大约98%的可能性您有一个bug。您有没有充分的理由不使用已建立的缓存库提供的功能,比如Ehcache的SelfPopulatingCache
发布于 2011-07-30 06:55:28
文档中说replace是原子的,所以我会这样做:
public V get(K key){
TimedItem ti;
ti = store.get(key);
if(ti == null)
return null;
long currentTime = new Date().getTime();
if((currentTime - ti.getTimeStored()) > expiryInMilliSec){
ti = new TimedItem(getItemFromSource(key));
store.replace(key, ti);
}
return ti.getItem();
}https://stackoverflow.com/questions/6879683
复制相似问题