Pergunta

I would like create a cache object with a factory, for a multiple tables. Each cache has their own life time which are different to one another. For example, lifetime for City object is about a year, and lifetime for facility list object is about 1 day.

This below is my cache class

public abstract class CacheAbstract<E, I, C> {

private Long timestamp;
private Class<E> entityClass;
private Class<I> idClass;
private Class<C> cacheClass;
protected Integer TTL = 60; // In minutes. defaults to 60 mins

private Map<I, C> cache;
private Timer timer;

public CacheAbstract(Class<E> entityClass, Class<I> idClass, Class<C> cacheClass) {
    this.entityClass = entityClass;
    this.idClass = idClass;
    this.cacheClass = cacheClass;
}

public Boolean isExpired() {
    return (this.timestamp + TTL * 60000) < new Date().getTime();
}

private void verifyCache() {
    if (this.cache == null || isExpired()) {
        this.load();
    }
}

private void onTimer() {
    this.timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            throw new UnsupportedOperationException("Not supported yet."); //What should I do here? I can't call this class' load(), can I?;
        }
    }, this.TTL * 60000);
}


public void load() {
    // Load all data here
    this.timestamp = new Date().getTime();
}

public C get(I id) {
    this.verifyCache();
    return this.cache.get(id);
}

public List<C> getAll() {
    this.verifyCache();
    List<C> list = new ArrayList<>(this.cache.values());
    return list;
}

protected abstract C transform(E entity);

protected abstract I getID(E entity);

public abstract String getName();
}

this class is not a singleton, and will be instantiated by a factory., let's say, CacheFactory

public final class CacheFactory {

private Map<String, CacheAbstract> caches;

private CacheFactory() {
}

public void registerCache(CacheAbstract cache) {
    if (caches == null) {
        caches = new HashMap<>();
    }
    if (caches.containsKey(cache.getName())) {
        this.caches.get(cache.getName()).load();
    } else {
        this.caches.put(cache.getName(), cache);
    }
}

public CacheAbstract getCache(String name) throws ExceptionInvalidCacheName {
    if (caches.containsKey(name)) {
        return caches.get(name);
    } else {
        throw new ExceptionInvalidCacheName("KOLOM SERVER [cache]: Cache '" + name + "' not registered");
    }
}

public Boolean isExist(String name) {
    return caches.containsKey(name);
}

public List<String> getNames() {
    return new ArrayList<>(caches.keySet());
}

public static CacheFactory getInstance() {
    return CacheFactoryHolder.INSTANCE;
}

private static class CacheFactoryHolder {

    private static final CacheFactory INSTANCE = new CacheFactory();
}
}

Now, how I can implement algorithm to let CacheAbstract to refresh itself when needed?

Foi útil?

Solução

Yes, you can simply call load():

private void onTimer() {
    timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {
             load(); // Call the containing class method
        }
    }, TTL * 60000);
}

because every anonymous class is actually also an inner class, so it has a reference to the containing class that declares it.

But, you would only use a Timer if you really wanted active expiration. You already have lazy expiration due to the call to verifyCache() in every call to get(). Maybe that's enough for your needs now.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top