美文网首页
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