2

我正在开发一个基于 Web 的医疗应用程序,需要创建一个小的内存对象缓存。这是我的用例。

我们需要显示需要某些东西(血液、肾脏等)的人提交的请求列表,并且它不会是一个巨大的列表,因为在给定的一天请求血液或其他任何东西都是有限的。请考虑到我们不想使用任何缓存 API,因为它会是一个矫枉过正。这个想法是创建一个 Map 并将其放置在 ApplicationContext 中。

任何人发出新请求的那一刻,我们将在应用程序上下文中更新该 Map,并且在请求过期的那一刻,我们将从 Map 中删除它们。我们还需要研究以下几点。

  1. 需要设置最大元素限制。
  2. 如果达到最大限制,我们应该删除最先添加的条目。
  3. 处理任何同步问题。

请建议应该使用什么数据结构以及在实施时要注意什么。

4

4 回答 4

2

谷歌的番石榴缓存怎么样?它实现起来非常简单,而且非常易于使用:

番石榴缓存

于 2012-08-11T07:35:52.667 回答
1

对于 OmniFaces 项目,我们有类似的要求,我们选择了concurrentlinkedhashmap,它带有一个小型包装器,用于跟踪缓存项的有效时间,并在请求该项时从缓存中懒惰地清除它们。

另请参阅:如何在 Java 中实现 LRU 缓存?

于 2012-08-11T07:40:15.417 回答
1

如果您不想添加第三方库,您可以在LinkedHashMap之上自己实现一个。LinkedHashMap 非常适合用作缓存,您可以配置策略(删除最近最少使用或最旧的条目)如果您进行相应配置,它将根据需要删除最旧的条目。
为了线程安全,您始终可以使用Collections#synchronizedMap()

这是一个小例子

于 2012-08-11T07:40:19.763 回答
0

我相信LinkedHashMap正是您所需要的。您只需要覆盖removeEldestEntry(...)方法,如果达到最大容量,它将自动为您删除旧条目。就像是:

import java.util.*;

class CacheMap<K,V> extends LinkedHashMap<K,V> {
    protected final int maxCapacity;
    public CacheMap(int maxCapacity) {
        this.maxCapacity = maxCapacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > maxCapacity;
    }
}

您可以实现更复杂的逻辑,例如删除非常旧的条目,即使最大值。容量未达到。

如果同步原子映射操作对您来说已经足够了,您可以将映射包装到Collections.synchronizedMap(...) 中

Map<K,V> map = Collections.synchronizedMap(new CacheMap<K,V>(capacity));

如果您需要更准确的同步,例如读取地图并在一个同步块中更新它,您需要自己同步与地图一起使用的 (所有)代码块。

于 2012-08-11T07:56:25.603 回答