Created
October 14, 2011 21:45
-
-
Save magro/1288448 to your computer and use it in GitHub Desktop.
A simple cache that holds all entries for a given type and updates itself in the background to keep the cache up to date.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Locale; | |
import java.util.Map; | |
import java.util.Timer; | |
import java.util.TimerTask; | |
import java.util.concurrent.atomic.AtomicReference; | |
/** | |
* A simple cache that holds all entries for a given type and updates itself in the | |
* background to keep the cache up to date. | |
* | |
* @author Martin Grotzke | |
* | |
* @param <K> | |
* the type of cache keys. | |
* @param <V> | |
* the type of cached values. | |
*/ | |
public class FullObjectCache<K, V> { | |
public static void main(String[] args) throws InterruptedException { | |
final List<String> sor = new ArrayList<String>(Arrays.asList("Foo")); | |
final CacheLoader<String> cacheLoader = new CacheLoader<String>() { | |
public Iterable<String> loadAll() { | |
return sor; | |
} | |
}; | |
final KeyGenerator<String, String> keyGenerator = new KeyGenerator<String, String>() { | |
public String getKey(String a) { | |
return a.toLowerCase(Locale.ENGLISH); | |
} | |
}; | |
final FullObjectCache<String, String> cache = new FullObjectCache<String, String>( | |
cacheLoader, keyGenerator, 100); | |
System.out.println("Found value for foo: " + cache.get("foo")); | |
System.out.println("Found value for bar: " + cache.get("bar")); | |
sor.add("Bar"); | |
Thread.sleep(200); | |
System.out.println("Found value for bar: " + cache.get("bar")); | |
cache.shutdown(); | |
} | |
public static interface CacheLoader<V> { | |
/** | |
* Loads all items that shall be cached. | |
*/ | |
Iterable<V> loadAll(); | |
} | |
public static interface KeyGenerator<A, B> { | |
/** | |
* Transforms an A to a B. | |
*/ | |
B getKey(A a); | |
} | |
private final CacheLoader<V> cacheLoader; | |
private final KeyGenerator<V, K> keyGenerator; | |
private final AtomicReference<Map<K, V>> entries; | |
private final Timer timer; | |
/** | |
* Creates a new cache that's updated in the specified reloadInterval. | |
* | |
* @param cacheLoader | |
* used to load all items to cache. | |
* @param keyGenerator | |
* used to generate the cache key for a cached value. | |
* @param reloadInterval | |
* interval in milliseconds to reload the cache. | |
*/ | |
public FullObjectCache(final CacheLoader<V> cacheLoader, | |
final KeyGenerator<V, K> keyGenerator, | |
final long reloadInterval) { | |
this.cacheLoader = cacheLoader; | |
this.keyGenerator = keyGenerator; | |
entries = new AtomicReference<Map<K, V>>(); | |
// as it takes some time until the timer task / thread is started and run | |
// we update the cache in this thread and use the reloadInterval as initial delay | |
updateCache(); | |
timer = new Timer(true); | |
timer.scheduleAtFixedRate(new TimerTask() { | |
@Override | |
public void run() { | |
updateCache(); | |
} | |
}, reloadInterval, reloadInterval); | |
} | |
/** | |
* Shutdown this cache and free acquired resources. | |
*/ | |
public void shutdown() { | |
timer.cancel(); | |
} | |
/** | |
* Triggers an update of the cache, returns when the update is finished. | |
*/ | |
public void updateCache() { | |
final Iterable<V> items = cacheLoader.loadAll(); | |
final Map<K, V> entries = new HashMap<K, V>(); | |
for (final V v : items) { | |
entries.put(keyGenerator.getKey(v), v); | |
} | |
this.entries.set(entries); | |
} | |
/** | |
* Get a cached value by the given cache key or <code>null</code> if not existing. | |
* | |
* @param key | |
* the cache key, must not be <code>null</code>. | |
* | |
* @return the cached value if existing, otherwise <code>null</code>. | |
*/ | |
public V get(final K key) { | |
return entries.get().get(key); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment