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 LRUCache的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. Java HashMap的死循环 以及 LRUCache的正确实现

    今天RP爆发,16核服务器load飙到30多,cpu使用情况全部99%以上. 从jstack中分析发现全部线程都堵在map.transfer处,如下: "pool-10-thread-23& ...

  3. 一个最简单的LRUCache实现 (JAVA)

    流程图: 1. 代码 import java.util.ArrayList; public class LRUCache { private int cacheMaxSize = 0; private ...

  4. java LinkedHashMap实现LRUCache缓存

    package java_map; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map ...

  5. Java容器解析系列(17) LruCache详解

    在之前讲LinkedHashMap的时候,我们说起可以用来实现LRU(least recent used)算法,接下来我看一下其中的一个具体实现-----android sdk 中的LruCache. ...

  6. Java集合之LinkedHashMap

    一.初识LinkedHashMap 上篇文章讲了HashMap.HashMap是一种非常常见.非常有用的集合,但在多线程情况下使用不当会有线程安全问题. 大多数情况下,只要不涉及线程安全问题,Map基 ...

  7. LruCache算法原理及实现

    LruCache算法原理及实现 LruCache算法原理 LRU为Least Recently Used的缩写,意思也就是近期最少使用算法.LruCache将LinkedHashMap的顺序设置为LR ...

  8. Java 对象引用方式 —— 强引用、软引用、弱引用和虚引用

    Java中负责内存回收的是JVM.通过JVM回收内存,我们不需要像使用C语音开发那样操心内存的使用,但是正因为不用操心内存的时候,也会导致在内存回收方面存在不够灵活的问题.为了解决内存操作不灵活的问题 ...

  9. LruCache为GridView异步加载大量网络图片

    MainActivity如下: import android.os.Bundle; import android.widget.GridView; import android.app.Activit ...

随机推荐

  1. 解决idea的.gitignore有时不起作用的问题

    有时候,.gitignore会对部分文件/文件夹失效,大概原因是由于新创建的文件已经出现在git本地仓库的缓存,所以.gitignore就失效了 解决办法就是清空一下git仓库的缓存,重新提交一次就好 ...

  2. Flume+Sqoop+Azkaban笔记

    大纲(辅助系统) 离线辅助系统 数据接入 Flume介绍 Flume组件 Flume实战案例 任务调度 调度器基础 市面上调度工具 Oozie的使用 Oozie的流程定义详解 数据导出 sqoop基础 ...

  3. [数据结构] P2.3 Trie树

    1.Trie树的概念 Trie树也叫做`字典树`或者`单词查找树`.用于字符串以及字符串元信息的快速查询. 例如:

  4. LeetCode--027--移除元素(java)

    给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...

  5. Java并发编程的艺术· 笔记(1)

    目录 1.volatile的原理 2.Synchonized 3.无锁-偏向锁-轻量级锁-重量级锁 4.Java实现原子操作 1.volatile的原理 如何保持可见性: 1)将当前处理器缓存行的数据 ...

  6. 初识Log4Net

    刚刚了解log4net,根据自己的理解翻译了一下比较重要的东西.详细状况请见log4net官方网站 log4net是一种帮助程序员将日志语句输出到各种目标文件的输出工具,有了log4net,就可以在运 ...

  7. SpringBoot使用日志

    1.日志框架 日志门面 日志实现 JCL.SLF4J.jboss-logging Log4j.JUL.Log4j2.Logback 日志门面:SLF4J 日志实现:Logback SpringBoot ...

  8. 函数调用模式,this指向

    ## 函数的四种调用模式 1.函数模式    this--->window function test(){ console.log(this); } test(): 2.方法模式    thi ...

  9. OSPFv3与OSPF的配置

    IPv6 路由-OSPFv3 实验目的 1.   掌握 OSPFv3 的配置方法 2.   掌握在帧中继环境下 OSPFv3 的配置方法 3.   掌握 OSPFv3 NSSA 的配置方法 4.   ...

  10. 简单的python购物车

                 这几天,一直在学python,跟着视频老师做了一个比较简单的python购物车,感觉不错,分享一下 products = [['Iphone8',6888],['MacPro ...