ExpiringMap 或基于 TTL 的缓存

ExpiringMap or TTL based Cache

http://www.java2s.com/Code/Java/Collections-Data-Structure/ExpiringMap.htm

Q1) 我在看上面的缓存代码。我很困惑为什么我们在调用 getLastAccessTime 时需要锁。该方法仅由 Expirer 线程调用。

Q2) 比方说,如果 Map 仅由线程调用,那么我们是否需要在 ExpiringObject 中使用可重入锁。因为 setLastAccessTime 在调用 Map 的 put 方法时只有线程调用,而 getLastAccessTime 方法将由 Expirer 线程调用。 我问的原因是,我测试插入1M对象,Reentrant Lock占用超过100MB

需要锁,因为 long 值不能在 32 位系统上自动更新。

备选方案:

  • 用 Long 替换 long。引用更新是原子的。

  • 使用 AtomicLong

  • 继续使用 Lock 对象,但使用大小约为可用 CPU 数量两倍的静态锁数组,并使用 locks[hashCode() % locks.length]

最后一个选项:使用缓存,它已经以优化的方式执行此操作,例如 EHCache、Google Guava 或 cache2k。

为了回答您的问题,我不太确定为什么 lastAccessTimeLock 需要锁定,因为对它的更改不需要与对其他任何内容的更改(原子地)一致。 IMO,它不需要锁。不过,您可能希望确保其他线程可以看到对 lastAccessTimeLock 的更改,这可以通过将其标记为 volatile 或使用 AtomicLong.

来实现

至于您的内存使用问题,您可以查看此 ExpiringMap 库而不是使用 Mina 实现。