zoukankan      html  css  js  c++  java
  • 本地缓存

    1.单机本地缓存

    本地缓存的一种简单实现

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

    /** 
    * 
    *本地缓存保存的实体 
    */  
    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;  
      }  
      
    }  
    /**
    * 简易本地缓存的实现类
    */
    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();
        }
    
        /**
        * 过期处理线程
        *
        */
        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);
                }
            }
        }
    
    }

    转载:https://www.iteye.com/blog/wujiu-2179087

    本地缓存的思想

    本地缓存会把数据放在内存中。所以不宜太大,否则容易造成内存不足

    因为是放在内存中,所以对于分布式部署,需要考虑到缓存数据的同步。

    1.可以建个缓存应用用来单独存放缓存。其他应用先访问缓存应用,没有得到缓存再访问数据库

    2.不进行缓存同步。这台机器没有缓存,就重新去获取。有的话直接使用本机缓存

    3.如果缓存同步要求型比较高,建议直接使用redis

  • 相关阅读:
    Docker创建tomcat镜像简单使用
    Eclipse和Jdk版本问题
    HashTable源码阅读
    HashMap源码阅读
    报错:Multiple annotations found at this line:
    python全栈开发学习03
    python全栈开发学习 02
    关于termux在手机上搭载Linux系统,python,ssh
    python全栈开发学习 01
    机器学习实战
  • 原文地址:https://www.cnblogs.com/linhongwenBlog/p/13356707.html
Copyright © 2011-2022 走看看