zoukankan      html  css  js  c++  java
  • Java 本地缓存的实现

          在java web 项目中对频繁读取且相对稳定的数据一般都是用了缓存,这样可以极大地减少数据库的压力且提高的响应的速度。 一般都是,通过key 从缓存中读取value 如果value 为空则读取DB,将DB读取的数据再放入缓存这样的一个过程。

    一个简易的本地缓存实现。

          首先数据一般都是有时效性的,不是放入缓存就一直存在,如果超过一定时间没有被使用则应当被清空,使其系统中不会使用到过期数据。

          下面是对本地缓存的一种简单实现

               首先定义一个缓存实体,包含三个属性 放入缓存的时间戳,值以及过期时间;其次需要个线程去监控缓存实体是否过期。

    /**
    *
    * @author zhangwei_david
    * @version $Id: CacheEntity.java, v 0.1 2014年9月6日 下午2:07:00 Lenovo Exp $
    */
    /**
    *本地缓存保存的实体
    *
    * @author Lenovo
    * @version $Id: LocalCache.java, v 0.1 2014年9月6日 下午1:13:43 Lenovo Exp $
    */
    public class CacheEntity implements Serializable {
    
    /** */
    private static final long serialVersionUID = 7172649826282703560L;
    
    /**
    * 值
    */
    private Object value;
    
    /**
    * 保存的时间戳
    */
    private long gmtModify;
    
    /**
    * 过期时间
    */
    private int expire;
    
    public Object getValue() {
    return value;
    }
    
    public void setValue(Object value) {
    this.value = value;
    }
    
    public long getGmtModify() {
    return gmtModify;
    }
    
    public void setGmtModify(long gmtModify) {
    this.gmtModify = gmtModify;
    }
    
    public int getExpire() {
    return expire;
    }
    
    public void setExpire(int expire) {
    this.expire = expire;
    }
    
    public CacheEntity(Object value, long gmtModify, int expire) {
    super();
    this.value = value;
    this.gmtModify = gmtModify;
    this.expire = expire;
    }
    
    }
    /**
    * 简易本地缓存的实现类
    * @author zhangwei_david
    * @version $Id: LocalCache.java, v 0.1 2014年9月6日 下午1:04:53 zhangwei_david Exp $
    */
    public class LocalCache {
    //默认的缓存容量
    private static int DEFAULT_CAPACITY = 512;
    //最大容量
    private static int MAX_CAPACITY = 100000;
    //刷新缓存的频率
    private static int MONITOR_DURATION = 2;
    // 启动监控线程
    static {
    new Thread(new TimeoutTimerThread()).start();
    }
    //使用默认容量创建一个Map
    private static ConcurrentHashMap<String, CacheEntity> cache = new ConcurrentHashMap<String, CacheEntity>(
    DEFAULT_CAPACITY);
    
    /**
    * 将key-value 保存到本地缓存并制定该缓存的过期时间
    *
    * @param key
    * @param value
    * @param expireTime 过期时间,如果是-1 则表示永不过期
    * @return
    */
    public boolean putValue(String key, Object value, int expireTime) {
    return putCloneValue(key, value, expireTime);
    }
    
    /**
    * 将值通过序列化clone 处理后保存到缓存中,可以解决值引用的问题
    *
    * @param key
    * @param value
    * @param expireTime
    * @return
    */
    private boolean putCloneValue(String key, Object value, int expireTime) {
    try {
    if (cache.size() >= MAX_CAPACITY) {
    return false;
    }
    // 序列化赋值
    CacheEntity entityClone = clone(new CacheEntity(value, System.nanoTime(), expireTime));
    cache.put(key, entityClone);
    return true;
    } catch (Exception e) {
    e.printStackTrace();
    }
    return false;
    }
    
    /**
    *
    * 序列化 克隆处理
    * @param object
    * @return
    */
    private <T extends Serializable> T clone(T object) {
    T cloneObject = null;
    try {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(object);
    oos.close();
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bais);
    cloneObject = (T) ois.readObject();
    ois.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return cloneObject;
    }
    
    /**
    *从本地缓存中获取key对应的值,如果该值不存则则返回null
    *
    * @param key
    * @return
    */
    public Object getValue(String key) {
    return cache.get(key).getValue();
    
    }
    
    /**
    * 清空所有
    */
    public void clear() {
    cache.clear();
    }
    
    /**
    * 过期处理线程
    *
    * @author Lenovo
    * @version $Id: LocalCache.java, v 0.1 2014年9月6日 下午1:34:23 Lenovo Exp $
    */
    static class TimeoutTimerThread implements Runnable {
    public void run() {
    while (true) {
    try {
    System.out.println("Cache monitor");
    TimeUnit.SECONDS.sleep(MONITOR_DURATION);
    checkTime();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    
    /**
    * 过期缓存的具体处理方法
    * @throws Exception
    */
    private void checkTime() throws Exception {
    //"开始处理过期 ";
    
    for (String key : cache.keySet()) {
    CacheEntity tce = cache.get(key);
    long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()
    - tce.getGmtModify());
    //" 过期时间 : "+timoutTime);
    if (tce.getExpire() > timoutTime) {
    continue;
    }
    System.out.println(" 清除过期缓存 : " + key);
    //清除过期缓存和删除对应的缓存队列
    cache.remove(key);
    }
    }
    }
    
    }
  • 相关阅读:
    449. Serialize and Deserialize BST
    3. Longest Substring Without Repeating Characters
    2. Add Two Numbers
    240. Search a 2D Matrix II
    5. Longest Palindromic Substring
    数位DP专题(开坑。
    POJ 2356
    HDU 4055
    HDU 4054
    HDU 1559
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797795.html
Copyright © 2011-2022 走看看