A cache is an area of local memory that holds a copy of
frequently accessed data that is otherwise expensive to get or compute.
Examples:
Database Query, disk file or data report.
Cache will keep most recently used items if you will
try to add more items then max specified then the least used items will removed
which are expired.
We are using org.apache.commons.collections.map.LRUMap, which removes the least used entries from a fixed sized map.
Items will expire based on a time to live period. We created a separate daemon thread for the expiration of items, timestamp the last access and in a separate thread remove the items when the time to live limit is reached. We can reduce the memory pressure for applications that have long idle time in between accessing the cached objects.
InMemoryCacheMap.java
import java.util.ArrayList;
import
org.apache.commons.collections.MapIterator;
import
org.apache.commons.collections.map.LRUMap;
/**
* @author Rajesh.dixit
*/
public class InMemoryCacheMap<K, T> {
private long timeToLive;
private LRUMap cacheMap;
/**
* Class to store the object with last access time of object.
* */
protected class CacheObject {
public long lastAccessed
= System.currentTimeMillis();
public T value;
protected
CacheObject(T value) {
this.value =
value;
}
}
/**
* InMemoryCacheMap Constructor to create cache.
* @param timeToLive - time to live cache in memory.
* @param timerInterval
* @param maxItems
*/
public
InMemoryCacheMap(long timeToLive,long timerInterval,int maxItems) {
this.timeToLive = timeToLive;
cacheMap = new LRUMap(maxItems);
if (timeToLive >
0 && timerInterval > 0) {
/**
Clean up Daemon thread which will remove
* clear the cache after cross time interval.*/
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(timerInterval);
} catch (InterruptedException ex) {
}
cleanup();
}
}
});
t.setDaemon(true);
t.start();
}
}
@SuppressWarnings("unchecked")
public T get(K key)
{
synchronized (cacheMap) {
CacheObject c = (CacheObject) cacheMap.get(key);
if (c == null)
return null;
else {
c.lastAccessed = System.currentTimeMillis();
return c.value;
}
}
}
@SuppressWarnings("unchecked")
public void cleanup() {
long now = System.currentTimeMillis();
ArrayList<K> deleteKey = null;
synchronized (cacheMap) {
MapIterator itr = cacheMap.mapIterator();
deleteKey = new ArrayList<K>((cacheMap.size() / 2) + 1);
K key = null;
CacheObject cachObj = null;
while (itr.hasNext()) {
key = (K) itr.next();
cachObj = (CacheObject)
itr.getValue();
/**
Identify the data which crossed the threshold. */
if (cachObj!=null&&(now>(timeToLive+cachObj.lastAccessed))) {
deleteKey.add(key);
}
}
}
/** Remove the keys which crossed the threshold time. */
for (K key :
deleteKey) {
synchronized (cacheMap) {
cacheMap.remove(key);
}
Thread.yield();
}
}
public void remove(K key) {
synchronized (cacheMap) {
cacheMap.remove(key);
}
}
public int size() {
synchronized (cacheMap) {
return cacheMap.size();
}
}
public void put(K key, T value) {
synchronized (cacheMap) {
cacheMap.put(key, new CacheObject(value));
}
}
@Override
public String
toString() {
MapIterator itr = cacheMap.mapIterator();
StringBuilder sb = new StringBuilder();
int count = 0;
while(itr.hasNext())
{
K key = (K) itr.next();
CacheObject c = (CacheObject)
itr.getValue();
T value = (T)c.value;
String info = key+"="+value;
if(count>0) {
sb.append(",");
}
sb.append(info);
count++;
}
sb.insert(0, "[");
sb.insert(sb.length(), "]");
return
sb.toString();
}
}
AddRemoveObjectsTest.java
public class AddRemoveObjectsTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("Test: TestAddRemoveObjects:
\n");
AddRemoveObjectsTest.addRemoveObjectsTest();
}
private static void addRemoveObjectsTest() throws InterruptedException {
long timeToLiveInSeconds = 100;
long timerIntervalInSeconds = 1000; // miliseconds
int maxItems = 5;
InMemoryCacheMap<String,
String> cache =
new InMemoryCacheMap<String,String>
(timeToLiveInSeconds,timerIntervalInSeconds,maxItems);
cache.put("Report1", "Report1");
cache.put("Report2", "Report2");
cache.put("Report3", "Report3");
cache.put("Report4", "Report4");
cache.put("Report5", "Report5");
/* Check the cache element in
size.*/
System.out.println("5 Cache Object Added..");
System.out.println("Cache Size: " + cache.size());
System.out.println(cache);
/* Remove an element from cache
manually.*/
cache.remove("Report5");
System.out.println("One object removed...");
System.out.println("Cache Size: " + cache.size());
System.out.println(cache);
/* Add two elements while cache
memory has space for one.*/
cache.put("Report6", "Report6");
cache.put("Report7", "Report7");
System.out.println("Two objects Added but reached
maxItems so " +
"remove some old objects from
cache...");
System.out.println("Cache Size: " + cache.size());
System.out.println(cache);
/* Perform operation some time later
on cacha memory.*/
Thread.sleep(1000);
/* Cache will be cleared by daemon
thread as it will keep checking
* the time to live of each element after a
given timerInterval.*/
cache.put("Report8", "Report8");
cache.put("Report9", "Report9");
System.out.println("Two objects Added but reached
maxItems so " +
"remove some old objects from
cache...");
System.out.println("Cache Size: " + cache.size());
System.out.println(cache);
}
}
Output:
Test:
TestAddRemoveObjects:
5 Cache
Object Added..
Cache Size:
5
[Report1=Report1,Report2=Report2,Report3=Report3,Report4=Report4,Report5=Report5]
One object
removed...
Cache Size:
4
[Report1=Report1,Report2=Report2,Report3=Report3,Report4=Report4]
Two objects
Added but reached maxItems so remove some old objects from cache...
Cache Size:
5
[Report2=Report2,Report3=Report3,Report4=Report4,Report6=Report6,Report7=Report7]
Two objects
Added but reached maxItems so remove some old objects from cache...
Cache Size:
2
[Report8=Report8,Report9=Report9]
ExpiredCacheObjectsTest.java
public class ExpiredCacheObjectsTest {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
System.out.println("Test:
ExpiredCacheObjectsTest...");
ExpiredCacheObjectsTest.expiredCacheObjectsTest();
}
private static void expiredCacheObjectsTest() throws InterruptedException {
InMemoryCacheMap<String,
String> cache = new
InMemoryCacheMap<String, String>(1, 1, 10);
cache.put("Report1", "Report1");
cache.put("Report2", "Report2");
System.out.println("Cache
size: "+cache.size()+" Data:" + cache);
/** After 1 Second, both the reports able to removed.
* Wait for 4 second to print cache data*/
Thread.sleep(3000);
System.out.println("After
3 seconds…");
System.out.println("Cache
size: "+cache.size()+" Data:" + cache);
}
}
Output:
Test:
ExpiredCacheObjectsTest...
Cache size:
2 Data:[Report1=Report1,Report2=Report2]
After 3
seconds...
Cache size:
0 Data:[]
No comments:
Post a Comment