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 实现。
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 实现。