【发布时间】:2011-12-06 22:43:26
【问题描述】:
我想要一个HashMap<String, String>,这样每天午夜,缓存就会过期。
请注意,它是 J2EE 解决方案,因此多个线程可以访问它。
在 Java 中实现它的最佳方式是什么?
【问题讨论】:
标签: java caching monitoring lazy-evaluation
我想要一个HashMap<String, String>,这样每天午夜,缓存就会过期。
请注意,它是 J2EE 解决方案,因此多个线程可以访问它。
在 Java 中实现它的最佳方式是什么?
【问题讨论】:
标签: java caching monitoring lazy-evaluation
虽然其他建议可以用来计算到期时间,但需要注意的是:
hashmap 的过期可以延迟完成
即没有任何监控线程!
实现过期的最简单方法如下:
1) 扩展哈希映射,并创建一个本地nextMidtime(Long)变量,在构造函数中初始化为System.currentTime....。这将设置为等于下一个午夜时间,以毫秒为单位...
2) 将以下 sn-p 添加到“containsKey”和“get”方法(或任何其他负责确保数据不会过时的方法)的第一行如下:
if (currentTime> nextMidTime)
this.clear();
//Lets assume there is a getNextMidnight method which tells us the nearest midnight time after a given time stamp.
nextMidTime=getNextMidnight(System.currentTimeInMilliseconds);
【讨论】:
您希望哈希图中的每一件事都在午夜刷新?
如果是这样,我想我会创建一个新的哈希图并将其替换为原始哈希图。由于替换是在一个步骤中完成的,并且没有其他东西试图进行相同的更改,我相信它应该是线程安全的。
任何处于中间访问权限的内容都将被允许完成其访问权限。这假定没有其他任何东西持有对此哈希图的引用。
如果没有将对 hasmap 的引用合并到一个位置,那么我猜 hashmap.clear() 是您最好的选择,如果 hashmap 是同步的。
如果 hashmap 不同步,那么您只能从单个线程修改它,对吗?让那个线程调用hashmap.clear()。
我认为这涵盖了所有情况。
【讨论】:
您还可以考虑使用 Guava 的 CacheBuilder,它允许您创建其 Cache 接口的自定义实例。在其他有用的功能中,CacheBuilder 允许您根据自己的目的设置定时到期等。
编辑:我应该注意,您根据last access 或last write 设置条目的过期时间,所以这个建议不完全符合您的要求,即每晚冲洗一次。如果可以选择使用第三方 API,您可能仍会考虑更改您的设计。 Guava 是一个非常聪明的库恕我直言,而不仅仅是用于缓存。
【讨论】:
java.util.Timer 和 java.util.TimerTask 可能会很有用。
创建一个可以清除或重新创建HashMap 的TimerTask,并通过Timer 实例安排它在午夜执行。
例如:
// Public single shared hash map.
static Map<String, String> cached_map_ = new HashMap<String, String>();
public class Hash_map_resetter
extends TimerTask
{
// Constructor takes reference to containing
// Timer so it can reset itself after execution.
Hash_map_resetter(Timer a_timer) { timer_ = a_timer; }
// Clear cache.
public void run()
{
cached_map_ = new HashMap<String, String>();
System.out.println("Cached cleared");
timer_.schedule(new Hash_map_resetter(timer_), 100);
}
// Reference to containing Timer.
private final Timer timer_;
}
// Example initiation.
Timer t = new Timer();
t.schedule(new Hash_map_resetter(t), 100);
该示例只是每 100 毫秒重置一次。
有很多 Timer.schedule() 方法,有些采用 Date 并允许您指定午夜。
【讨论】:
HashMap,这样您就可以在包含HashMap 的类中定义一个嵌套类并启动计时器在外部类的构造函数中。