JAVA 实现本地缓存

JAVA 实现本地缓存(可直接复用)

本来想上传上去给大家要用积分下载的,后来想想算了,给大家直接免费用吧

网上的闲杂的代码太多,所以集成了一下,这个本人已经测试过,完成可以用,一共是两个类,一个是LocalCache,另外一个是CacheEntity

LocalCache 类(主类) ,实现本地缓存的主体


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName LocalCache
 * @Description
 * @Author 
 * @Date 
 * @Version 1.0
 */

public class LocalCache {

    private static final Logger log = LoggerFactory.getLogger(LocalCache.class);

    /**
     * 默认的缓存容量
     */
    private static final int DEFAULT_CAPACITY = 512;
    /**
     * 最大容量
     */
    private static final int MAX_CAPACITY = 100000;
    /**
     * 刷新缓存的频率
     */
    private static final int MONITOR_DURATION = 2;

    // 启动监控线程  
    static {
        new Thread(new TimeoutTimerThread()).start();
    }

    // 内部类方式实现单例
    private static class LocalCacheInstance{
        private static final LocalCache INSTANCE=new LocalCache();

    }
    public static LocalCache getInstance() {
        return LocalCacheInstance.INSTANCE;
    }

    private LocalCache() {
    }

    /**
     * 使用默认容量创建一个Map
     */
    private static Map<String, CacheEntity> cache = new ConcurrentHashMap<>(DEFAULT_CAPACITY);

    /**
     * 将key-value 保存到本地缓存并制定该缓存的过期时间
     *
     * @param key
     * @param value
     * @param expireTime 过期时间
     * @return
     */
    public <T> boolean putValue(String key, T value, int expireTime) {
        return putCloneValue(key, value, expireTime);
    }

    /**
     * 将值通过序列化clone 处理后保存到缓存中,可以解决值引用的问题
     *
     * @param key
     * @param value
     * @param expireTime
     * @return
     */
    private <T> boolean putCloneValue(String key, T value, int expireTime) {
        try {
            if (cache.size() >= MAX_CAPACITY) {
                return false;
            }
            // 序列化赋值 license缓存是直接加入object所以序列化克隆不需要
            CacheEntity entityClone = new CacheEntity(value, System.nanoTime(), expireTime);
            cache.put(key, entityClone);
            return true;
        } catch (Exception e) {
            log.error("添加缓存失败:{}", e.getMessage());
        }
        return false;
    }

    /**
     * 序列化 克隆处理
     *
     * @param object
     * @return
     */
    private <E extends Serializable> E clone(E object) {
        E 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 = (E) ois.readObject();
            ois.close();
        } catch (Exception e) {
            log.error("缓存序列化失败:{}", e.getMessage());
        }
        return cloneObject;
    }

    /**
     * 从本地缓存中获取key对应的值,如果该值不存则则返回null
     *
     * @param key
     * @return
     */
    public Object getValue(String key) {
        //加入为空判断,若不加则报错
        if (cache.get(key) == null){
            return null;
        }
        return cache.get(key).getValue();
    }

    /**
     * 清空所有
     */
    public void clear() {
        cache.clear();
    }

    /**
     * 过期处理线程
     */
    static class TimeoutTimerThread implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(MONITOR_DURATION);
                    checkTime();
                } catch (Exception e) {
                    log.error("过期缓存清理失败:{}", e.getMessage());
                }
            }
        }

        /**
         * 过期缓存的具体处理方法
         *
         * @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;
                }
                log.info(" 清除过期缓存 : " + key);
                //清除过期缓存和删除对应的缓存队列
                cache.remove(key);
            }
        }
    }
}

---------------------------------------------------------------------------------------------------------------------------------------- 

CacheEntity类

import lombok.Data;

import java.io.Serializable;

@Data
public class CacheEntity implements Serializable {

    private static final long serialVersionUID = 2594373766348228819L;

    /**
     * 值
     */
    private Object value;

    /**
     * 保存的时间戳
     */
    private long gmtModify;

    /**
     * 过期时间
     */
    private int expire;

    public CacheEntity(Object value, long gmtModify, int expire) {
        super();
        this.value = value;
        this.gmtModify = gmtModify;
        this.expire = expire;
    }

}

@Data 是lombok的注解,大家可以直接用get,set解决,这我就懒得写

下面写几个示例

LocalCache localCache = LocalCache.getInstance();  //初始化本地缓存

LicenseVO license = (LicenseVO)localCache.getValue(CacheKey.LICENSE); //根据本地缓存自定义的名称获取

localCache.putValue(CacheKey.LICENSE,license,0); //永不过期,放入缓存的参数

基本这几个方法,大部分的业务代码都能搞了。就这,谢谢大家。

 

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值