zoukankan      html  css  js  c++  java
  • 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.Consumer;
    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 {
            public TV            value;
            private int          expireSeconds;
            private DateTime     createTime;
            private Consumer<TV> expireCallback;
    
            public CacheItem(TV value, int expireSeconds, Consumer<TV> expireCallback) {
                this.value = value;
                this.expireSeconds = expireSeconds;
                this.expireCallback = expireCallback;
                refresh();
            }
    
            public void refresh() {
                if (expireSeconds > -1) {
                    createTime = DateTime.utcNow();
                }
            }
    
            public void callback() {
                if (expireCallback != null) {
                    expireCallback.accept(value);
                }
            }
        }
    
        private static final Lazy<LRUCache<String, Object>> instance = new Lazy<>(() -> new LRUCache<>(1000, 120));
    
        public static LRUCache<String, Object> getInstance() {
            return instance.getValue();
        }
    
        public static Object getOrStore(String key, Function<String, Object> supplier) {
            require(key, supplier);
    
            return getInstance().getOrAdd(App.cacheKey(key), p -> supplier.apply(key));
        }
    
        private final Map<TK, CacheItem> cache;
        private int                      maxCapacity;
        private int                      expireSeconds;
        private Consumer<TV>             expireCallback;
        private Future                   future;
    
        public LRUCache(int maxSize, int expireSecondsAfterAccess) {
            this(maxSize, expireSecondsAfterAccess, 8 * 1000, null);
        }
    
        public LRUCache(int maxSize, int expireSecondsAfterAccess, long checkPeriod, Consumer<TV> removeCallback) {
            cache = Collections.synchronizedMap(new LinkedHashMap<TK, CacheItem>(maxSize + 1, .75F, true) {
                @Override
                protected boolean removeEldestEntry(Map.Entry<TK, CacheItem> eldest) {
                    boolean remove = size() > maxCapacity;
                    if (remove) {
                        eldest.getValue().callback();
                    }
                    return remove;
                }
            });
            maxCapacity = maxSize;
            expireSeconds = expireSecondsAfterAccess;
            expireCallback = removeCallback;
            future = TaskFactory.schedule(() -> {
                for (Map.Entry<TK, CacheItem> entry : NQuery.of(cache.entrySet()).where(p -> p.getValue().expireSeconds > -1
                        && DateTime.utcNow().addSeconds(-p.getValue().expireSeconds).after(p.getValue().createTime))) {
                    entry.getValue().callback();
                    cache.remove(entry.getKey());
                }
            }, checkPeriod);
        }
    
        @Override
        protected void freeObjects() {
            if (future != null) {
                future.cancel(true);
            }
            cache.clear();
        }
    
        public void add(TK key, TV val) {
            add(key, val, expireSeconds, expireCallback);
        }
    
        public void add(TK key, TV val, int expireSecondsAfterAccess, Consumer<TV> removeCallback) {
            require(key);
    
            cache.put(key, new CacheItem(val, expireSecondsAfterAccess, removeCallback));
        }
    
        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, expireCallback));
            } else {
                item.refresh();
            }
            return item.value;
        }
    }
  • 相关阅读:
    Java 创建过滤器 解析xml文件
    web页面隐藏鼠标
    dom4j微信接口开发
    php实现远程网络文件下载到服务器指定目录 阿星小栈
    laravel 框架给$request添加数据 阿星小栈
    Agreeing to the Xcode/iOS license requires admin privileges, please run “sudo xcodebuild -license” and then retry this command. 阿星小栈
    在vue项目中使用echarts 阿星小栈
    js 数组、时间、邮箱等处理方法 阿星小栈
    iview 在Table组件render 中使用Poptip组件 阿星小栈
    逐步解决动态添加样式导致的元素闪烁 阿星小栈
  • 原文地址:https://www.cnblogs.com/Googler/p/10353496.html
Copyright © 2011-2022 走看看