• java LRUCache


    package org.rx.cache;
    
    import org.rx.common.*;
    import org.rx.beans.DateTime;
    
    import java.util.Collections;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.concurrent.Future;
    import java.util.function.Function;
    
    import static org.rx.common.Contract.as;
    import static org.rx.common.Contract.require;
    import static org.rx.util.AsyncTask.TaskFactory;
    
    public final class LRUCache<TK, TV> extends Disposable {
        private class CacheItem {
            private TV       value;
            private DateTime createTime;
            private int      expireSeconds;
    
            public CacheItem(TV value, int expireSeconds) {
                this.value = value;
                this.expireSeconds = expireSeconds;
                refresh();
            }
    
            public void refresh() {
                createTime = DateTime.utcNow();
            }
        }
    
        private static final Lazy<LRUCache<String, Object>> instance = new Lazy<>(
                () -> new LRUCache<>(200, 120, 30 * 1000));
    
        public static LRUCache<String, Object> getInstance() {
            return instance.getValue();
        }
    
        public static Object getOrStore(Class caller, String key, Function<String, Object> supplier) {
            require(caller, key, supplier);
    
            String k = App.cacheKey(caller.getName() + key);
            return getInstance().getOrAdd(k, p -> supplier.apply(key));
        }
    
        private final Map<TK, CacheItem> cache;
        private int                      maxCapacity;
        private int                      expireSeconds;
        private Future                   future;
    
        public LRUCache(int maxSize, int expireSecondsAfterAccess, long checkPeriod) {
            cache = Collections.synchronizedMap(new LinkedHashMap<TK, CacheItem>(maxSize + 1, .75F, true) {
                @Override
                protected boolean removeEldestEntry(Map.Entry<TK, CacheItem> eldest) {
                    return size() > maxCapacity;
                }
            });
            maxCapacity = maxSize;
            expireSeconds = expireSecondsAfterAccess;
            future = TaskFactory.schedule(() -> {
                for (TK k : NQuery.of(cache.entrySet())
                        .where(p -> p.getValue().expireSeconds > -1
                                && DateTime.utcNow().addSeconds(-p.getValue().expireSeconds).after(p.getValue().createTime))
                        .select(p -> p.getKey())) {
                    cache.remove(k);
                    Logger.debug("LRUCache remove {}", k);
                }
            }, checkPeriod);
        }
    
        @Override
        protected void freeObjects() {
            if (future != null) {
                future.cancel(true);
            }
            cache.clear();
        }
    
        public void add(TK key, TV val) {
            add(key, val, expireSeconds);
        }
    
        public void add(TK key, TV val, int expireSecondsAfterAccess) {
            require(key);
    
            cache.put(key, new CacheItem(val, expireSecondsAfterAccess));
        }
    
        public void remove(TK key) {
            remove(key, true);
        }
    
        public void remove(TK key, boolean destroy) {
            require(key);
            CacheItem remove = cache.remove(key);
            if (remove == null) {
                return;
            }
    
            AutoCloseable ac;
            if (destroy && (ac = as(remove.value, AutoCloseable.class)) != null) {
                try {
                    ac.close();
                } catch (Exception ex) {
                    Logger.error(ex, "Auto close error");
                }
            }
        }
    
        public TV get(TK key) {
            require(key);
    
            CacheItem item = cache.get(key);
            if (item == null) {
                return null;
            }
            item.refresh();
            return item.value;
        }
    
        public TV getOrAdd(TK key, Function<TK, TV> supplier) {
            require(key, supplier);
    
            CacheItem item = cache.get(key);
            if (item == null) {
                cache.put(key, item = new CacheItem(supplier.apply(key), expireSeconds));
            } else {
                item.refresh();
            }
            return item.value;
        }
    }
  • 相关阅读:
    002-pythn基础-循环、编码
    001-python3 初识
    confluence6.x安装
    python+ffmpeg切割视频
    Elasticsearch6.x和Kibana6.x的安装
    django基础
    CDH的完全离线安装(ubuntu16)
    python之旅十【第十篇】paramiko模块
    解决 MariaDB无密码就可以登录的问题
    切割日志(mysql,nginx,php tomcat)使用logrotate
  • 原文地址:https://www.cnblogs.com/Googler/p/10250958.html
Copyright © 2020-2023  润新知