ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Freemarker源码分析(3)cache.CacheStorage及其子类

2021-10-24 22:00:04  阅读:243  来源: 互联网

标签:return Freemarker 子类 Object private 源码 key entry public


2021SC@SDUSC

Freemarker源码分析(3)cache.CacheStorage及其子类

cache.CacheStorage及其子类

总览图
在这里插入图片描述

1.CacheStorage接口

代码

public interface CacheStorage {
    public Object get(Object key);
    public void put(Object key, Object value);
    public void remove(Object key);
    public void clear();
}

作用:Cache storage抽象了高速缓存的存储方面——将对象(object)与键(key)相关联,通过键进行检索和删除。它实际上是java.util.Map的一个子接口。

2.CacheStorageWithGetSize接口

代码

public interface CacheStorageWithGetSize extends CacheStorage {
    int getSize();
}

作用:具有getSize()方法的缓存存储,用于返回当前缓存条目的数量。

3.ConcurrentCacheStorage接口

代码

public interface ConcurrentCacheStorage extends CacheStorage {
    public boolean isConcurrent();
}

作用:一个可选的缓存存储接口,它知道是否可以在不同步的情况下并发访问。

4.NullCacheStorage类

代码

public class NullCacheStorage implements ConcurrentCacheStorage, CacheStorageWithGetSize {
    
    public static final NullCacheStorage INSTANCE = new NullCacheStorage();

    @Override
    public boolean isConcurrent() {
        return true;
    }
    
    @Override
    public Object get(Object key) {
        return null;
    }

    @Override
    public void put(Object key, Object value) {
        // do nothing
    }

    @Override
    public void remove(Object key) {
        // do nothing
    }
    
    @Override
    public void clear() {
        // do nothing
    }

    public int getSize() {
        return 0;
    }
    
}

作用:一个不存储任何东西的高速缓存存储器。如果不需要缓存,可以使用这个。

5.SoftCacheStorage类

代码

public class SoftCacheStorage implements ConcurrentCacheStorage, CacheStorageWithGetSize {
    private static final Method atomicRemove = getAtomicRemoveMethod();
    
    private final ReferenceQueue queue = new ReferenceQueue();
    private final Map map;
    private final boolean concurrent;
    
    public SoftCacheStorage() {
        this(new ConcurrentHashMap());
    }
    
    @Override
    public boolean isConcurrent() {
        return concurrent;
    }
    
    public SoftCacheStorage(Map backingMap) {
        map = backingMap;
        this.concurrent = map instanceof ConcurrentMap;
    }
    
    @Override
    public Object get(Object key) {
        processQueue();
        Reference ref = (Reference) map.get(key);
        return ref == null ? null : ref.get();
    }

    @Override
    public void put(Object key, Object value) {
        processQueue();
        map.put(key, new SoftValueReference(key, value, queue));
    }

    @Override
    public void remove(Object key) {
        processQueue();
        map.remove(key);
    }

    @Override
    public void clear() {
        map.clear();
        processQueue();
    }
    
    @Override
    public int getSize() {
        processQueue();
        return map.size();
    }

    private void processQueue() {
        for (; ; ) {
            SoftValueReference ref = (SoftValueReference) queue.poll();
            if (ref == null) {
                return;
            }
            Object key = ref.getKey();
            if (concurrent) {
                try {
                    atomicRemove.invoke(map, new Object[] { key, ref });
                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new UndeclaredThrowableException(e);
                }
            } else if (map.get(key) == ref) {
                map.remove(key);
            }
        }
    }

    private static final class SoftValueReference extends SoftReference {
        private final Object key;

        SoftValueReference(Object key, Object value, ReferenceQueue queue) {
            super(value, queue);
            this.key = key;
        }

        Object getKey() {
            return key;
        }
    }
    
    private static Method getAtomicRemoveMethod() {
        try {
            return Class.forName("java.util.concurrent.ConcurrentMap").getMethod("remove", new Class[] { Object.class, Object.class });
        } catch (ClassNotFoundException e) {
            return null;
        } catch (NoSuchMethodException e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}

作用:软缓存存储是一种使用SoftReference对象来保存传递给它的对象的缓存存储,因此允许垃圾收集器在确定想要释放内存时清除缓存。这个类的线程安全程度与其底层映射相同。无参数构造函数使用自2.3.24或Java 5以上的线程安全映射。

6.StrongCacheStorage类

代码

public class StrongCacheStorage implements ConcurrentCacheStorage, CacheStorageWithGetSize {
    
    private final Map map = new ConcurrentHashMap();

    @Override
    public boolean isConcurrent() {
        return true;
    }
    
    @Override
    public Object get(Object key) {
        return map.get(key);
    }

    @Override
    public void put(Object key, Object value) {
        map.put(key, value);
    }

    @Override
    public void remove(Object key) {
        map.remove(key);
    }
    
    @Override
    public int getSize() {
        return map.size();
    }
    
    @Override
    public void clear() {
        map.clear();
    }
}

作用:强缓存存储是简单封装Map的缓存存储。它持有对传递给它的所有对象的强引用,因此可以防止在垃圾收集期间清除缓存。

7.MruCacheStorage类

代码

public class MruCacheStorage implements CacheStorageWithGetSize {
    private final MruEntry strongHead = new MruEntry();
    private final MruEntry softHead = new MruEntry();
    {
        softHead.linkAfter(strongHead);
    }
    private final Map map = new HashMap();
    private final ReferenceQueue refQueue = new ReferenceQueue();
    private final int strongSizeLimit;
    private final int softSizeLimit;
    private int strongSize = 0;
    private int softSize = 0;
    
    public MruCacheStorage(int strongSizeLimit, int softSizeLimit) {
        if (strongSizeLimit < 0) throw new IllegalArgumentException("strongSizeLimit < 0");
        if (softSizeLimit < 0) throw new IllegalArgumentException("softSizeLimit < 0");
        this.strongSizeLimit = strongSizeLimit;
        this.softSizeLimit = softSizeLimit;
    }
    
    @Override
    public Object get(Object key) {
        removeClearedReferences();
        MruEntry entry = (MruEntry) map.get(key);
        if (entry == null) {
            return null;
        }
        relinkEntryAfterStrongHead(entry, null);
        Object value = entry.getValue();
        if (value instanceof MruReference) {
            // This can only happen with strongSizeLimit == 0
            return ((MruReference) value).get();
        }
        return value;
    }

    @Override
    public void put(Object key, Object value) {
        removeClearedReferences();
        MruEntry entry = (MruEntry) map.get(key);
        if (entry == null) {
            entry = new MruEntry(key, value);
            map.put(key, entry);
            linkAfterStrongHead(entry);
        } else {
            relinkEntryAfterStrongHead(entry, value);
        }
        
    }

    @Override
    public void remove(Object key) {
        removeClearedReferences();
        removeInternal(key);
    }

    private void removeInternal(Object key) {
        MruEntry entry = (MruEntry) map.remove(key);
        if (entry != null) {
            unlinkEntryAndInspectIfSoft(entry);
        }
    }

    @Override
    public void clear() {
        strongHead.makeHead();
        softHead.linkAfter(strongHead);
        map.clear();
        strongSize = softSize = 0;
        // Quick refQueue processing
        while (refQueue.poll() != null);
    }

    private void relinkEntryAfterStrongHead(MruEntry entry, Object newValue) {
        if (unlinkEntryAndInspectIfSoft(entry) && newValue == null) {
            // Turn soft reference into strong reference, unless is was cleared
            MruReference mref = (MruReference) entry.getValue();
            Object strongValue = mref.get();
            if (strongValue != null) {
                entry.setValue(strongValue);
                linkAfterStrongHead(entry);
            } else {
                map.remove(mref.getKey());
            }
        } else {
            if (newValue != null) {
                entry.setValue(newValue);
            }
            linkAfterStrongHead(entry);
        }
    }

    private void linkAfterStrongHead(MruEntry entry) {
        entry.linkAfter(strongHead);
        if (strongSize == strongSizeLimit) {
            // softHead.previous is LRU strong entry
            MruEntry lruStrong = softHead.getPrevious();
            // Attila: This is equaivalent to strongSizeLimit != 0
            // DD: But entry.linkAfter(strongHead) was just executed above, so
            //     lruStrong != strongHead is true even if strongSizeLimit == 0.
            if (lruStrong != strongHead) {
                lruStrong.unlink();
                if (softSizeLimit > 0) {
                    lruStrong.linkAfter(softHead);
                    lruStrong.setValue(new MruReference(lruStrong, refQueue));
                    if (softSize == softSizeLimit) {
                        // List is circular, so strongHead.previous is LRU soft entry
                        MruEntry lruSoft = strongHead.getPrevious();
                        lruSoft.unlink();
                        map.remove(lruSoft.getKey());
                    } else {
                        ++softSize;
                    }
                } else {
                    map.remove(lruStrong.getKey());
                }
            }
        } else {
            ++strongSize;
        }
    }

    private boolean unlinkEntryAndInspectIfSoft(MruEntry entry) {
        entry.unlink();
        if (entry.getValue() instanceof MruReference) {
            --softSize;
            return true;
        } else {
            --strongSize;
            return false;
        }
    }
    
    private void removeClearedReferences() {
        for (; ; ) {
            MruReference ref = (MruReference) refQueue.poll();
            if (ref == null) {
                break;
            }
            removeInternal(ref.getKey());
        }
    }
    
    public int getStrongSizeLimit() {
        return strongSizeLimit;
    }

    public int getSoftSizeLimit() {
        return softSizeLimit;
    }

    public int getStrongSize() {
        return strongSize;
    }

    public int getSoftSize() {
        removeClearedReferences();
        return softSize;
    }
    
    @Override
    public int getSize() {
        return getSoftSize() + getStrongSize();
    }

    private static final class MruEntry {
        private MruEntry prev;
        private MruEntry next;
        private final Object key;
        private Object value;
        
        MruEntry() {
            makeHead();
            key = value = null;
        }
        
        MruEntry(Object key, Object value) {
            this.key = key;
            this.value = value;
        }
        
        Object getKey() {
            return key;
        }
        
        Object getValue() {
            return value;
        }
        
        void setValue(Object value) {
            this.value = value;
        }

        MruEntry getPrevious() {
            return prev;
        }
        
        void linkAfter(MruEntry entry) {
            next = entry.next;
            entry.next = this;
            prev = entry;
            next.prev = this;
        }
        
        void unlink() {
            next.prev = prev;
            prev.next = next;
            prev = null;
            next = null;
        }
        
        void makeHead() {
            prev = next = this;
        }
    }
    
    private static class MruReference extends SoftReference {
        private final Object key;
        
        MruReference(MruEntry entry, ReferenceQueue queue) {
            super(entry.getValue(), queue);
            this.key = entry.getKey();
        }
        
        Object getKey() {
            return key;
        }
    }
    
    
}

作用:实现两级最近使用缓存的缓存存储。在第一层中,项被强引用到指定的最大值。当超过最大值时,最近最少使用的项被移动到第二级缓存,在那里它们被软引用,直到另一个第二级缓存,在那里它们被软引用,直到另一个最近使用的项被完全丢弃。这个缓存存储是StrongCacheStorage和SoftCacheStorage的一般化-两者的效果都可以通过设置一个最大值为零,另一个最大值为最大的正整数来实现。

注:Freemarker代码来自FreeMarker 中文官方参考手册

新手写的代码分析,文章若有错误还请指出

标签:return,Freemarker,子类,Object,private,源码,key,entry,public
来源: https://blog.csdn.net/qq_43518847/article/details/120940942

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有