美文网首页
tomcat 源码中的简易缓存 ConcurrentCache

tomcat 源码中的简易缓存 ConcurrentCache

作者: 田才 | 来源:发表于2020-10-26 20:37 被阅读0次

    关于tomcat源码包中 org.apache.el.util.ConcurrentCache 线程安全缓存,

    是基于java.util.concurrent.ConcurrentHashMap 和 java.util.WeakHashMap 实现的,存放固定大小的数据 java.util.concurrent.ConcurrentHashMap ,当超过固定大小的数据存放在 java.util.WeakHashMap 中,当jvm进行垃圾回收时候,
    java.util.WeakHashMap 的内容会被回收掉,以此保证多余的缓存不占用过多的内存。简单实用

    
    public final class ConcurrentCache<K,V> {
    
        //常驻内容的大小
        private final int size;
    
        //常驻缓存
        private final Map<K,V> eden;
    
        //存放多余的内容
        private final Map<K,V> longterm;
    
        public ConcurrentCache(int size) {
            this.size = size;
            this.eden = new ConcurrentHashMap<>(size);
            this.longterm = new WeakHashMap<>(size);
        }
    
        public V get(K k) {
           //从常驻缓存中获取内容
            V v = this.eden.get(k);
            if (v == null) {
                synchronized (longterm) {
                    v = this.longterm.get(k);
                }
                //非常住缓存如果不为空,那么尝试将内容存放在eden
                if (v != null) {
                    this.eden.put(k, v);
                }
            }
            return v;
        }
    
        public void put(K k, V v) {
            //如果超过常驻缓存的大小
            if (this.eden.size() >= size) {
                synchronized (longterm) {
                    this.longterm.putAll(this.eden);
                }
                //清空常驻缓存
                this.eden.clear();
            }
            this.eden.put(k, v);
        }
    }
    
    

    看代码的流程非常向浇灌田地的水车系统中的那个水桶

    再看下 jdk 的 WeakHashMap 的实现

    主要依赖ReferenceQueue<Object> queue 和 WeakReference ,这对组合是 jvm 发生垃圾回收时,将 WeakReference 的实现类存放到 ReferenceQueue 中,但是此时 WeakReference 的 T referent 已经jvm被回收。WeakHashMap 的get 和put 和 size 方法中会循环 ReferenceQueue 然后重新调整table 的大小

    
        private void expungeStaleEntries() {
            for (Object x; (x = queue.poll()) != null; ) {
                synchronized (queue) {
                    @SuppressWarnings("unchecked")
                        Entry<K,V> e = (Entry<K,V>) x;
                    int i = indexFor(e.hash, table.length);
    
                    Entry<K,V> prev = table[i];
                    Entry<K,V> p = prev;
                    while (p != null) {
                        Entry<K,V> next = p.next;
                        if (p == e) {
                            if (prev == e)
                                table[i] = next;
                            else
                                prev.next = next;
                            // Must not null out e.next;
                            // stale entries may be in use by a HashIterator
                            e.value = null; // Help GC
                            size--;
                            break;
                        }
                        prev = p;
                        p = next;
                    }
                }
            }
        }
    

    相关文章

      网友评论

          本文标题:tomcat 源码中的简易缓存 ConcurrentCache

          本文链接:https://www.haomeiwen.com/subject/terzmktx.html