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 LRUCache的更多相关文章
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- Java HashMap的死循环 以及 LRUCache的正确实现
今天RP爆发,16核服务器load飙到30多,cpu使用情况全部99%以上. 从jstack中分析发现全部线程都堵在map.transfer处,如下: "pool-10-thread-23& ...
- 一个最简单的LRUCache实现 (JAVA)
流程图: 1. 代码 import java.util.ArrayList; public class LRUCache { private int cacheMaxSize = 0; private ...
- java LinkedHashMap实现LRUCache缓存
package java_map; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map ...
- Java容器解析系列(17) LruCache详解
在之前讲LinkedHashMap的时候,我们说起可以用来实现LRU(least recent used)算法,接下来我看一下其中的一个具体实现-----android sdk 中的LruCache. ...
- Java集合之LinkedHashMap
一.初识LinkedHashMap 上篇文章讲了HashMap.HashMap是一种非常常见.非常有用的集合,但在多线程情况下使用不当会有线程安全问题. 大多数情况下,只要不涉及线程安全问题,Map基 ...
- LruCache算法原理及实现
LruCache算法原理及实现 LruCache算法原理 LRU为Least Recently Used的缩写,意思也就是近期最少使用算法.LruCache将LinkedHashMap的顺序设置为LR ...
- Java 对象引用方式 —— 强引用、软引用、弱引用和虚引用
Java中负责内存回收的是JVM.通过JVM回收内存,我们不需要像使用C语音开发那样操心内存的使用,但是正因为不用操心内存的时候,也会导致在内存回收方面存在不够灵活的问题.为了解决内存操作不灵活的问题 ...
- LruCache为GridView异步加载大量网络图片
MainActivity如下: import android.os.Bundle; import android.widget.GridView; import android.app.Activit ...
随机推荐
- sourcetree,创建工作流报错:Fatal: Not a gitflow-enabled repo yet. Please run 'git flow init' first.-》解决办法
1.打开项目下.git/config文件,或者如下图操作: 2.打开config文件以后,删除所有 [gitflow *条目并保存文件 3.关闭并重新打开sourcetree 4.仓库->Git ...
- 基于vue 、vue-router 、firebase的todolist小项目
第一次写博客,都不知道改怎么写的好. 本着一颗学习的心,也希望一段时间后再回来在看看自己写的代码,会不会让自己有种不忍直视的念头 *-* 还是先上图吧~ 这是首页,主要是展示所有的列表页面,可以通过输 ...
- 在Rancher 1.6上部署Traefik负载均衡器
一.给Traefik主机打标签 01-给即将部署Traefik的主机节点打上标签.jpg 02-主机打完traefik_lb标签后的状态.jpg 二.在Rancher应用商店中部署Traefik 应用 ...
- Mysql8 查询事务隔离级别
Mysql8 查询事务隔离级别 SELECT @@TRANSACTION_ISOLATION REPEATABLE-READ ---默认隔离级别(可重复读)
- C#的Monitor.Enter和Monitor.Exit
C#的lock 语句实际上是调用Monitor.Enter和Monitor.Exit,中间夹杂try-finally语句的简略版,下面是实际发生在之前例 子中的Go方法: 1 2 3 4 5 6 7 ...
- mpvue开发项目总结(从0到上线)
1.简言 为期一个半月的小程序开发,其中夹杂其他项目的功能迭代,跌跌撞撞的将项目完成了,今天中秋节放假前一天,以此来记录下此次打怪升级的心得与分享其中遇到花费时间的问题. 因为此次开发的是一个类电商项 ...
- vue-element-ui之弹窗重置
遇到列表中需要给弹框赋默认值并且关闭后需要清空数据+清除验证时可以这么写:
- kafka AdminClient 闲时关闭连接
AdminClient 类提供了创建.删除 topic 的 api. 在项目中创建了一个 AdminClient 对象,每次创建 topic 时,调用 org.apache.kafka.clients ...
- react中的传参方式
react是一个SPA模式,即组件嵌套租,在一个单页面的应用中组件间的数值传递是必不可少的,主要的传参方式大致有一下几种: 1,在挂载的地方给组件传参 ReactDOM.rander(<a na ...
- GDAL——命令使用专题——ogrinfo命令
GDAL——命令使用专题——ogrinfo命令 前言 GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库.它利用抽象 ...