package pay.infrastructure.helper;
import org.apache.commons.collections.MapIterator;
import org.apache.commons.collections.map.LRUMap;
import java.util.ArrayList;
/**
* Created by wangxiaoming on 2016/3/14.
*/
public class InMemoryCache {
protected class CrunchifyCacheObject {
public long lastAccessed;
public TV value;
protected CrunchifyCacheObject(TV value) {
lastAccessed = System.currentTimeMillis();
this.value = value;
}
}
private long timeToLive;
private LRUMap crunchifyCacheMap;
public InMemoryCache(long crunchifyTimeToLive, final long crunchifyTimerInterval, int maxItems) {
crunchifyCacheMap = new LRUMap(maxItems);
this.timeToLive = crunchifyTimeToLive * 1000;
if (timeToLive > 0 && crunchifyTimerInterval > 0) {
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(crunchifyTimerInterval * 1000);
} catch (InterruptedException ex) {
}
cleanup();
}
}
});
t.setDaemon(true);
t.start();
}
}
public void put(TK key, TV value) {
synchronized (crunchifyCacheMap) {
crunchifyCacheMap.put(key, new CrunchifyCacheObject(value));
}
}
@SuppressWarnings("unchecked")
public TV get(TK key) {
synchronized (crunchifyCacheMap) {
CrunchifyCacheObject c = (CrunchifyCacheObject) crunchifyCacheMap.get(key);
if (c == null) {
return null;
} else {
c.lastAccessed = System.currentTimeMillis();
return c.value;
}
}
}
public void remove(TK key) {
synchronized (crunchifyCacheMap) {
crunchifyCacheMap.remove(key);
}
}
public int size() {
synchronized (crunchifyCacheMap) {
return crunchifyCacheMap.size();
}
}
@SuppressWarnings("unchecked")
public void cleanup() {
long now = System.currentTimeMillis();
ArrayList deleteKey = null;
synchronized (crunchifyCacheMap) {
MapIterator itr = crunchifyCacheMap.mapIterator();
deleteKey = new ArrayList<>((crunchifyCacheMap.size() / 2) + 1);
while (itr.hasNext()) {
TK key = (TK) itr.next();
CrunchifyCacheObject c = (CrunchifyCacheObject) itr.getValue();
if (c != null && (now > (timeToLive + c.lastAccessed))) {
deleteKey.add(key);
}
}
}
for (TK key : deleteKey) {
synchronized (crunchifyCacheMap) {
crunchifyCacheMap.remove(key);
}
Thread.yield();
}
}
}