All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jodd.cache.AbstractCacheMap Maven / Gradle / Ivy

Go to download

Jodd Core tools and utilities, including type converters, JDateTime, cache etc.

There is a newer version: 5.3.0
Show newest version
// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.cache;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Default implementation of timed and size cache map.
 * Implementations should:
 * 
    *
  • create a new cache map
  • *
  • implements own prune strategy
  • *
* Uses ReentrantReadWriteLock to synchronize access. * Since upgrading from a read lock to the write lock is not possible, * be careful withing {@link #get(Object)} method. */ public abstract class AbstractCacheMap implements Cache { class CacheObject { CacheObject(K2 key, V2 object, long ttl) { this.key = key; this.cachedObject = object; this.ttl = ttl; this.lastAccess = System.currentTimeMillis(); } final K2 key; final V2 cachedObject; long lastAccess; // time of last access long accessCount; // number of accesses long ttl; // objects timeout (time-to-live), 0 = no timeout boolean isExpired() { if (ttl == 0) { return false; } return lastAccess + ttl < System.currentTimeMillis(); } V2 getObject() { lastAccess = System.currentTimeMillis(); accessCount++; return cachedObject; } } protected Map> cacheMap; private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(); private final Lock readLock = cacheLock.readLock(); private final Lock writeLock = cacheLock.writeLock(); // ---------------------------------------------------------------- properties protected int cacheSize; // max cache size, 0 = no limit /** * {@inheritDoc} */ public int getCacheSize() { return cacheSize; } protected long timeout; // default timeout, 0 = no timeout /** * Returns default cache timeout or 0 if it is not set. * Timeout can be set individually for each object. */ public long getCacheTimeout() { return timeout; } /** * Identifies if objects has custom timeouts. * Should be used to determine if prune for existing objects is needed. */ protected boolean existCustomTimeout; /** * Returns true if prune of expired objects should be invoked. * For internal use. */ protected boolean isPruneExpiredActive() { return (timeout != 0) || existCustomTimeout; } // ---------------------------------------------------------------- put /** * {@inheritDoc} */ public void put(K key, V object) { put(key, object, timeout); } /** * {@inheritDoc} */ public void put(K key, V object, long timeout) { writeLock.lock(); try { CacheObject co = new CacheObject(key, object, timeout); if (timeout != 0) { existCustomTimeout = true; } if (isFull()) { pruneCache(); } cacheMap.put(key, co); } finally { writeLock.unlock(); } } // ---------------------------------------------------------------- get protected int hitCount; protected int missCount; /** * Returns hit count. */ public int getHitCount() { return hitCount; } /** * Returns miss count. */ public int getMissCount() { return missCount; } /** * {@inheritDoc} */ public V get(K key) { readLock.lock(); try { CacheObject co = cacheMap.get(key); if (co == null) { missCount++; return null; } if (co.isExpired() == true) { // remove(key); // can't upgrade the lock cacheMap.remove(key); missCount++; return null; } hitCount++; return co.getObject(); } finally { readLock.unlock(); } } /** * {@inheritDoc} */ public Iterator iterator() { return new CacheValuesIterator(this); } // ---------------------------------------------------------------- prune /** * Prune implementation. */ protected abstract int pruneCache(); /** * {@inheritDoc} */ public final int prune() { writeLock.lock(); try { return pruneCache(); } finally { writeLock.unlock(); } } // ---------------------------------------------------------------- common /** * {@inheritDoc} */ public boolean isFull() { if (cacheSize == 0) { return false; } return cacheMap.size() >= cacheSize; } /** * {@inheritDoc} */ public void remove(K key) { writeLock.lock(); try { cacheMap.remove(key); } finally { writeLock.unlock(); } } /** * {@inheritDoc} */ public void clear() { writeLock.lock(); try { cacheMap.clear(); } finally { writeLock.unlock(); } } /** * {@inheritDoc} */ public int size() { return cacheMap.size(); } /** * {@inheritDoc} */ public boolean isEmpty() { return size() == 0; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy