zoukankan      html  css  js  c++  java
  • Java进程内缓存

    今天和同事聊到了缓存,在Java中实现进程缓存。这里主要思想是,用一个map做缓存。缓存有个生存时间,过期就删除缓存。这里可以考虑两种删除策略,一种是起一个线程,定期删除过期的key。第二个是,剔除模式,比较懒,访问到某个key的时候才,才去检查这个key是否过期,过期删除。

    首先,对要缓存的value做了层封装,带了个时间戳

    /**
     * Created by gxf on 2017/6/28.
     */
    public class ValueWithTimeStamp<V>{
        private long expireTime;
        private V value;
    
        public ValueWithTimeStamp(long expireTime, V value) {
            this.expireTime = expireTime;
            this.value = value;
        }
    
        public long getExpireTime() {
            return expireTime;
        }
    
        public void setExpireTime(long expireTime) {
            this.expireTime = expireTime;
        }
    
        public V getValue() {
            return value;
        }
    
        public void setValue(V value) {
            this.value = value;
        }
    }

    ok,起线程定期删除策略的模式

    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * Created by gxf on 2017/6/28.
     * 使用线程,定期删除过期的key
     */
    public class CacheMap<K, V>  {
        //这里使用ConcurrentHashMap避免,clean的时候,主线程修改chache,造成异常,
        //使用ConcurrentHashMap可以控制并发修改cache
        private Map<K, ValueWithTimeStamp<V>> cache = new ConcurrentHashMap<K, ValueWithTimeStamp<V>>();
        private static boolean cleanTaskIsRunning = false;
    
        //ttl 过期时间 单位:秒
        public void put(K key, V value, int ttl){
            long expireTime = System.currentTimeMillis() + ttl * 1000;
            ValueWithTimeStamp<V> valueWithTimeStamp = new ValueWithTimeStamp<>(expireTime, value);
            cache.put(key, valueWithTimeStamp);
            if(!cleanTaskIsRunning){
                startCleanTask();
                cleanTaskIsRunning = !cleanTaskIsRunning;
            }
        }
    
        public V get(K key){
            ValueWithTimeStamp<V> valueWithTimeStamp = cache.get(key);
            return null == valueWithTimeStamp ? null : valueWithTimeStamp.getValue();
        }
    
        /**
         * 启动清理线程
         * */
        private void startCleanTask(){
            Thread cleanThread = new Thread(new CleanTask());
            cleanThread.start();
        }
    
        /**
         * 清理过期的key
         * */
        class CleanTask implements Runnable{
            public void run(){
                while(true){
                    long currentTime =  System.currentTimeMillis();
                    //遍历map
                    for(Map.Entry<K, ValueWithTimeStamp<V>> entry : cache.entrySet()){
                        ValueWithTimeStamp<V> valueWithTimeStamp = entry.getValue();
                        long expireTime = valueWithTimeStamp.getExpireTime();
                        //过期时间到了
                        if(currentTime > expireTime){
                            System.out.println("key : " + entry.getKey() + " expired ");
                            cache.remove(entry.getKey());
                        } //if
                    } //for
                    //每隔1s扫描map对象
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } //while
            }
        }
    }

    注意,这里需要使用ConcurrentHashMap做缓存。不然会出现多线线程操作map对象的异常

    第二种策略,剔除模式

    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * Created by 58 on 2017/6/28.
     * 这里使用懒惰模式,获取key的时候,才剔除过期的key
     */
    public class CacheMap1<K, V> {
        private Map<K, ValueWithTimeStamp<V>> cache = new ConcurrentHashMap<K, ValueWithTimeStamp<V>>();
    
        public void put(K key, V value, int ttl){
            long expireTime = System.currentTimeMillis() + ttl * 1000;
            ValueWithTimeStamp<V> valueWithTimeStamp = new ValueWithTimeStamp<V>(expireTime, value);
            cache.put(key, valueWithTimeStamp);
        }
    
        public V get(K key){
            ValueWithTimeStamp<V> valueWithTimeStamp = cache.get(key);
            long expireTime = valueWithTimeStamp.getExpireTime();
            long currentTime = System.currentTimeMillis();
            //key已经过期,删除,返回null
            if(currentTime > expireTime){
                System.out.println("key :" + key + " is expired.");
                cache.remove(key);
                return null;
            }
    
            return cache.get(key).getValue();
        }
    }

    项目中用到了redis,用这种方式应该会更快,这两天优化一下代码

  • 相关阅读:
    一、Dapper基本操作
    Javascript基础--函数(Function对象)
    【Selenium专题】FAQ_浏览器_ChromeDriver版本导致报错
    mvn install 报错Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2 错误: 找不到符号
    Eclipse中mvn install 报错error in opening zip file
    Maven项目编译时报错缺少tools.jar
    maven-compiler-plugin 版本错误解决方法
    【QTP专题-优化】VBS脚本启动QTP并运行测试
    QTP 场景恢复– 函数调用
    达梦数据库(DaMeng)如何删除IDENTITY自增属性字段
  • 原文地址:https://www.cnblogs.com/luckygxf/p/7091793.html
Copyright © 2011-2022 走看看