- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用 Caffeine 作为 LRU 缓存,因此首先添加的条目将首先被逐出。运行这段代码:
final Cache<Object, Object> map = Caffeine.newBuilder()
.maximumSize(10)
.initialCapacity(10)
.build();
for (long i=0; i<20;i++) {
map.put(i, i);
}
map.cleanUp();
System.out.println(map.ge.getAllPresent(map.asMap().keySet()));
打印:
{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 19=19}
但我预料到了
{10=10, 11=11, 12=12, 13=13, 14=14, 15=15, 16=16, 17=17, 18=18, 19=19}
我做错了什么?
最佳答案
Caffeine 没有实现 LRU 作为其缓存逐出策略。相反,Caffeine 使用名为 TinyLFU 的策略. Caffeine 文档包括关于 Efficiency 的页面,其中讨论了这种设计选择的基本原理。引用该页面:
TinyLfu
relies on a frequency sketch to probabilistically estimate the historic usage of an entry.
由于 Caffeine 实际上并没有实现 LRU,我认为当您检查缓存中的条目时,您不能可靠地期望它表现出严格的 LRU 行为。
如果您绝对必须具有 LRU 行为,那么 JDK 标准 LinkedHashMap
是一个很好的、直接的选择。您需要对其进行子类化并覆盖 removeEldestEntry
当缓存变得比你想要的大时,逻辑会发出信号。如果需要使用多线程,则需要使用适当的同步来包装操作。
咖啡因深受 Guava Cache 启发,它同样提供并发访问并具有近似 LRU 行为。针对 Guava 缓存对您的代码进行的快速测试显示了类似的结果。我不知道有任何标准库可以提供可预测的、外部可观察的 LRU 结果和真正的并发访问而无需粗粒度锁。
您可能会重新考虑是否真的需要严格的、外部可观察的 LRU 结果。就其本质而言,缓存是提供优化查找的快速临时存储。我不认为程序行为会根据缓存是否实现严格的 LRU、LRU、LFU 的近似值或其他一些逐出策略而发生巨大变化。
这个先前的问题也对 Java 中的 LRU 缓存选项进行了很好的讨论。
关于java - 含咖啡因的 LRU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34694920/
Caffeine 有 expiresAfterWrite 方法,可以查看上次写入时间。我希望它只查看创建时间。因此,当第一个条目到来时,条目将在固定的时间后过期,而无需查看该条目的更新次数。这可能吗?
我有一个计算密集型的一次性离线处理任务,需要几个小时才能运行,我正在使用 Caffeine作为我的内存缓存。设置最大缓存大小的好的启发式方法是什么?我正在使用 8GB 的 RAM 运行我的 Jav
我想配置Caffeine缓存以在加载程序无法刷新缓存时返回陈旧的结果。以下Kotlin代码演示了这种情况: @Test fun `completeble future`() = run
我们使用caffeine来替换当前springboot中默认的ConcurrentHashMap缓存。我们使用 @Cacheable(cacheNames = { "..."}) 注释动态创建缓存。
我无法运行 caffeinate 命令 caffeinate The program 'caffeinate' is currently not installed. You can install
从 Java 8 开始,我们可以在 ConcurrentHashMap 上使用 .compute* 方法来按 key 同步处理,这样如果两个线程同时对同一个 key 执行 .compute* 方法,回
我是一名优秀的程序员,十分优秀!