在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);
- }
- }
- }
- }
相关推荐
JAXB允许我们将Java类与XML Schema定义的元素和类型绑定,从而实现XML的序列化和反序列化。 在Java对象和XML之间的转换过程中,JAXB主要涉及到以下几个关键概念: 1. **Java类与XML Schema绑定**: JAXB使用`@...
默认情况下,浏览器可能会从本地缓存中加载页面,而不是每次都从服务器获取,这可能导致用户看到的不是最新的内容。可以通过设置HTTP响应头来控制缓存策略,例如`Cache-Control: no-cache`或`Pragma: no-cache`。 ...
Ehcache 是一个开源的 Java 缓存库,它提供了本地内存缓存以及分布式缓存解决方案。在 Spring 框架中,Ehcache 可以被轻松地集成,以提升应用的性能,减少数据库的负载。这篇博客将深入探讨如何将 Ehcache 集成到 ...
不管是通过网络、本地文件、content provider还是本地资源,它都把图片压缩并缓存到磁盘,并且把内存作为第二缓存存储着解码后的图片 作者:r17171709 链接:https://www.jianshu.com/p/8ff81be83101 來源:简书 ...
Nginx的反向代理 ...tomcat+nginx+redis实现均衡负载、session共享(二)...好在redis提供了java客户端开发包,名曰jedis,下星期会比较忙,等过段时间再分享下使用jedis缓存数据的过程。 欢迎转载,但请先经过本人允许。