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<String,Object> cache = new ConcurrentHashMap<String, Object>();
    /**
     * 定时任务服务
     */
    private Timer timer = new Timer(true);
    /**
     * 定时任务集合
     */
    private Map<String,TimerTask> tasks = new ConcurrentHashMap<String, TimerTask>();
    
    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);
    }
}
最近下载更多
qcxdld  LV1 2020年9月23日
gan857569302  LV9 2020年6月23日
luohaipeng  LV23 2019年11月20日
低调人  LV38 2019年8月4日
Tiger_Peppa  LV2 2019年6月19日
幽幻梦之韩霜  LV10 2018年9月4日
1324488732  LV27 2017年12月22日
silent  LV12 2017年9月27日
zl_lin  LV2 2017年1月3日
zyl  LV34 2016年6月22日
最近浏览更多
CrystalQ  LV8 2023年5月30日
hxx123456789  LV10 2021年8月13日
qcxdld  LV1 2020年9月23日
wkc  LV21 2020年7月29日
gan857569302  LV9 2020年6月22日
luv583774  LV1 2020年6月11日
weixiao  LV6 2020年5月18日
1033755143  LV17 2020年5月8日
弥尘123456  LV4 2020年2月19日
luohaipeng  LV23 2019年11月20日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友