我正在尝试使用Caffeine作为LRU缓存,因此首先添加的条目将首先被逐出.跑这段代码:
final Cache
哪个印刷品:
{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}
我究竟做错了什么?
咖啡因不实施LRU作为其缓存驱逐策略.相反,Caffeine使用名为TinyLFU的政策.Caffeine文档包含有关效率的页面,该页面讨论了此设计选择的基本原理.引用该页面:
TinyLfu
依赖于频率草图来概率地估计条目的历史使用.
由于Caffeine实际上并不实现LRU,因此当您检查缓存中的条目时,我认为您不能可靠地期望它表现出严格的LRU行为.
如果你绝对必须有LRU行为,那么JDK标准LinkedHashMap
是一个很好的,直截了当的选择.您需要对其进行子类化并removeEldestEntry
使用逻辑覆盖,以便在缓存增长超过您想要的时间时发出信号.如果需要多线程使用,那么您需要使用适当的同步来包装操作.
咖啡因深受Guava Cache的启发,它同样提供并发访问并具有近似的LRU行为.针对Guava缓存快速测试代码显示了类似的结果.我不知道任何标准库可以提供可预测的,外部可观察的LRU结果和真正的并发访问,而无需粗粒度锁.
您可能会重新考虑是否真的需要具有严格的,外部可观察的LRU结果.就其本质而言,缓存是快速临时存储,以提供优化的查找.我不希望程序行为根据缓存是否实现严格的LRU,近似的LRU,LFU或其他一些驱逐策略而发生巨大变化.
这个先前的问题也对Java中的LRU缓存选项进行了很好的讨论.
您将如何在Java中实现LRU缓存?