private static MapurlItemCache = Collections.synchronizedMap(new HashMap ());
private static MapurlItemCacheTtl = Collections.synchronizedMap(new HashMap ());
private static final long TTL=1000*60*60;//one hour in milliseconds
public static String findItemByUrl( String url) {
String item="";
Long now=Long.valueOf(Calendar.getInstance().getTimeInMillis());
//try to get the item from the local cache
item = urlItemCache.get(url);
if ( !isEmpty(item)) {
//urlItemCacheTtl.get(url) is guaranteed to have a value, since it's added at the same time urlItemCache is.
if (now.longValue() - urlItemCacheTtl.get(url).longValue() < TTL ) {
urlItemCacheTtl.put(url, now);//see comment below
return item;
} else {
urlItemCache.remove(url);
urlItemCacheTtl.remove(url);
}
}
//not found in cache
//... do you application magic here to get the item ...
if ( !isEmpty(item) ) {
urlItemCache.put(url, item); //add to local cache
urlItemCacheTtl.put(url, now);
return item;
} //else
return null;
}
Wednesday, November 21, 2007
Java TTL Cache, the Quick and Dirty Way
There are many caching systems in java. I really like some of them (especially Ian Schumacher's LRU Cache). But sometimes you just to drop a quick few lines to get something in a local cache. Here is one way of doing it:
Labels:
java
Subscribe to:
Post Comments (Atom)
Has 2 common problems, it's not threadsafe, and hot objects never expire.
ReplyDeleteNice, but you need some locking to make it threadsafe.
Threadsafety:
private final Object lockObject=new Object();
and this around the get/puts.
synchronized (lockObject) {
};
Hot objects:
Don't do this:
if (now.longValue() - urlItemCacheTtl.get(url).longValue() < TTL ) {
urlItemCacheTtl.put(url, now);
that will cause frequent objects to never be re-requested.
Thanks Allen for the comment. I'll address the issues:
ReplyDelete1) Hot items: you are absolutely right. Stupid mistake on my side. fixing..
2) Thread safety: I am using synchronizedMap so the collection itself is theadsafe. You are right in that that it's possible to be inserting two objects almost together, however I prefer that risk (I don't really care if that happens since key/value pairs are always the same) as i wanted to keep the code simple and fast. YMMV.
Small point, but should likely use System.nanoTime() offsets to calculate TTL's to avoid odd behavour around daylight-savings events.
ReplyDelete