首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java缓存设计问题

Java缓存设计问题
EN

Stack Overflow用户
提问于 2011-07-30 06:31:46
回答 2查看 844关注 0票数 0

我正在写一个缓存实现-如果存储的项在存储中的时间超过5分钟,它就会过期。在这种情况下,应该从源刷新它,否则应该返回缓存的副本。

下面是我写的--它有没有设计上的缺陷?特别是get部分?

代码语言:javascript
复制
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();
}

}

EN

回答 2

Stack Overflow用户

发布于 2011-07-30 06:47:10

假设您正在尝试手动同步,并且(在猜测中)您似乎没有对其进行非常彻底的测试,我会说有大约98%的可能性您有一个bug。您有没有充分的理由不使用已建立的缓存库提供的功能,比如Ehcache的SelfPopulatingCache

票数 1
EN

Stack Overflow用户

发布于 2011-07-30 06:55:28

文档中说replace是原子的,所以我会这样做:

代码语言:javascript
复制
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();
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6879683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档