import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Timer;
import java.util.TimerTask;
/**
* 虚拟缓存服务器,模拟memcache缓存服务器,在本地没有对应环境的时候使用;
* 1、序列化原则:所有存入的数据必须是可序列化的
* 2、数据无关性:取出数据后修改,缓存数据不受影响,存入数据后在对源数据进行修改,缓存数据不受影响
* 3、覆盖原则:重复存入同一个key,会覆盖源数据与原时效
* 存在问题:
* 1、线程问题:需要定时清理的数据量越大,线程越多;
* 2、效率问题:深度克隆一个对象所带来的时间消耗,实测每次深度克隆大概在10ms左右;
* 优化方案:
* 1、针对线程问题:可以采用将所有的待处理task(非timertask)都放入一个map中,启动一个线程每隔x秒循环清理一次;但是这样实际上就不是实时清理,不过考虑到大部分现实情况,x秒一次的清理也是满足要求的;
* 2、效率问题:暂时没有较好的方法
* @author frank
*
*/
public class VirtualCache{
/**
* 是否开发模式,开发模式输出错误信息
*/
private boolean isdev = false;
private static String ERROR = "虚拟缓存数据存取异常";
/**
* 虚拟缓存
*/
private Map cache = new ConcurrentHashMap();
/**
* 定时任务服务
*/
private Timer timer = new Timer(true);
/**
* 定时任务集合
*/
private Map tasks = new ConcurrentHashMap();
public VirtualCache(boolean isdev){
this.isdev = isdev;
}
public VirtualCache(){
}
/**
* 添加定时任务
* 在过期后将缓存删除,并删除此定时任务
*/
private void addTimeOutTask(final String key,Long timeout){
TimerTask task = new TimerTask() {
public void run() {
delete(key);
tasks.remove(key);
}
};
tasks.put(key, task);
timer.schedule(task, timeout * 1000l);
}
/**
* 中止某个定时任务
*/
private void cancelExitTask(String key){
if(!tasks.containsKey(key))
return;
TimerTask task = tasks.get(key);
task.cancel();
tasks.remove(key);
}
/**
* 为了实现数据无关性,取出或者存入必须是值的深度克隆
*/
private Object clone(Object obj){
ByteArrayOutputStream bo = null;
ObjectOutputStream oo = null;
ByteArrayInputStream bi = null;
ObjectInputStream oi = null;
Object value = null;
try {
bo=new ByteArrayOutputStream();
oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
bi=new ByteArrayInputStream(bo.toByteArray());
oi=new ObjectInputStream(bi);
value = oi.readObject();
} catch (Exception e) {
System.err.println(ERROR);
if(this.isdev){
e.printStackTrace();
}
} finally{
if(oo != null)
try {
oo.close();
} catch (Exception e) {
System.err.println(ERROR);
if(this.isdev){
e.printStackTrace();
}
}
if(oi != null)
try {
oi.close();
} catch (Exception e) {
System.err.println(ERROR);
if(this.isdev){
e.printStackTrace();
}
}
}
return value;
}
/**
* 将数据放入缓存
* 如果tiemout<=0,则永远不过期
* 注意:重复存入同一个key,则覆盖原时限与原数据
*/
public void set(String key,Object value,long timeout){
this.cancelExitTask(key);
cache.put(key, this.clone(value));
if(timeout > 0l)
this.addTimeOutTask(key, timeout);
}
/**
* 获取数据
*/
public Object get(String key){
Object value = cache.get(key);
return value == null ? null : this.clone(value);
}
/**
* 删除缓存
*/
public void delete(String key){
cache.remove(key);
}
}