• 用Linkedhashmap的LRU特性及SoftReference软引用构建二级缓存


    LRU: least recently used(近期最少使用算法)。LinkedHashMap构造函数可以指定其迭代顺序:LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 设置accessOrder为true,则按照访问顺序迭代。当linkedhashmap调用put或者putall成功插入键值时,会调用removeEldestEntry方法,根据该方法的返回值决定是否删除最老对象(accessOrder为true后根据访问顺序迭代),为了保证map的size不超过某个值,可以重写removeEldestEntry方法,返回true,删除最老对象。

    softreference软引用,通过例如new SoftReference<Object>(new Object())这样的方式来保留对一个object的软引用,在即将OOM的时候,GC会将softreference引用的对象回收。所以,在内存充足的时候,它的get()方法返回的是它引用的对象,在因为即将OOM导致GC回收之后,它的get方法返回的是null。

    FirstCache.java:

    public class FirstCache<K,V> extends LinkedHashMap<K,V>{
        private static final long serialVersionUID = 1L;
        private int MAX_SIZE = 100;
        private SecondCache<K, V> secondCache = new SecondCache<K, V>();
        public FirstCache(){
            super();
        }
        public FirstCache(int max_size){
            //利用linkedHashMap构造方法的accessOrder属性来构建LRU缓存
            //accessOrder为true时,按照访问顺序排序,当accessOrder为false时,按照插入顺序排序
            super(100,0.75f,true);
            this.MAX_SIZE = max_size;
        }
        //当map调用put或者putall方法成功插入一个entry时,根据removeEldestEntry返回的bool值来确定是否删除least recently used对应的数据
        //返回true删除  返回false保留
        @Override
        protected boolean removeEldestEntry(Entry<K,V> entry) {
            if(size() >= MAX_SIZE){
                //用softreference的特点来做二级缓存,softreference(软引用)只有在即将oom的时候 GC才会回收
                secondCache.put(entry.getKey(), entry.getValue());
                System.out.println("二级缓存容量" + secondCache.notEmptySize());
                return true;
            }
            return false;
        }
    }

    SecondCache.java:

    public class SecondCache<K,V> {
        Map<K,SoftReference<V>> secondCacheMap = new HashMap<K, SoftReference<V>>();
        
        public void put(K k,V v){
            SoftReference<Object> o = new SoftReference<Object>(new Object());
            secondCacheMap.put(k, new SoftReference<V>(v));
        }
        
        /**
         * 将value为null的键值对删除,返回整个map中value不为null的数量
         */
        public int notEmptySize(){
            int count = 0;
            Iterator<Entry<K, SoftReference<V>>> iter = secondCacheMap.entrySet().iterator();
            while(iter.hasNext()){
                if(iter.next().getValue().get() == null)
                    iter.remove();
                else
                    count++;
            }
            return count;
        }
    }

    测试方法:将虚拟机参数设置为-Xms64M -Xmx64M:

    public class LRUCache {
        public static final int MAX_SIZE = 20;
        public static int count = 0;
        public static void main(String[] args){
            //一级缓存,利用linkedHashMap的LRU特性
            FirstCache<Integer, Student> firstCache = new FirstCache<Integer, Student>(20);
    //        HashMap<Integer, Student> m = new HashMap<Integer, Student>();
            while(true){
                count++;
                Student s = new Student();
                //如果直接使用hashmap来存放,在count大约59的时候就抛出OOM了
    //            m.put(count, s);
    //            System.out.println(count);
                firstCache.put(count, s);
                if(count > MAX_SIZE){
                    System.out.println(firstCache.size());
                }
            }
        }
        
        /**
         * 占用1M数据
         */
        static class Student{
            public byte[] datas = new byte[1024*1024];
        }
    }
  • 相关阅读:
    牛客网每日一练
    牛客网每日一练
    linux/nginx 安全增强 迎客
    ObjectiveC 对象复制 迎客
    在Xcode中搭建真机调试环境 迎客
    VirtualBox虚拟机Ubuntu找不到网卡的解决方法 迎客
    Xcode中创建和添加Libary 迎客
    做领导还是做自己? 迎客
    ObjcetiveC 归档 迎客
    ObjcetiveC 中 @property 介绍 迎客
  • 原文地址:https://www.cnblogs.com/hithlb/p/4151706.html
Copyright © 2020-2023  润新知