0

我的要求是维护一个固定大小的缓存,它为基于 Java 的 Web 应用程序中的多个消费者和单个生产者提供支持。我的数据是这样的:

键 1,键 2,值

123,ABC,列表1

123,定义,列表2

234,xyz,列表3

客户端或消费者将根据 key1 和 key2 查询此缓存。因此,如果多个消费者尝试同时访问相同 key1 和 2 的缓存,他们都应该从缓存中获取相同的数据作为响应。

我正在寻找可能使用的最佳数据结构。另请注意,缓存大小是固定的,因此如果生产者在尝试插入记录之前应该删除第一个元素(如果缓存已满)。

我目前在地图中使用地图。即键 1 用于外部映射,键 2 用于内部映射。但是,我需要查看它以获取我认为效率低下的信息。

有什么建议吗?

4

4 回答 4

1

首先,我会将您的缓存扁平化为单个、2 个组件键(即将 key1 和 key2 组合成一个复合键类)。

其次,我会使用现有的缓存实现而不是重新发明轮子。对于“简单”的用法,您可以同步对 LinkedHashMap 的访问(您可以使用该removeEldestEntry()方法按大小限制)。如果您需要更复杂的线程处理,那么我会看看ehcacheGuava之类的东西(在其他答案中提到)。

于 2012-12-14T17:14:27.390 回答
0

查看Guava,这是 Google 提供的一个有用的实用程序库,其中包含一些出色的缓存功能。特别是,它支持最大大小,并将自动处理驱逐。

至于 2 键问题,为什么不将 Guava 缓存(或任何实现)包装在另一个类中,该类采用 2 键并从组合中生成单个键,例如:

public class MyCache<Key, Value> {
    private final Cache<CacheKey, Value> guavaCache = CacheBuilder.build()

    public void put(Key keyOne, Key keyTwo, Value value) {
        cache.put(new CacheKey(keyOne, keyTwo), value);
    }

    public Value get(Key keyOne, Key keyTwo) {
        return cache.getIfPresent(new CacheKey(keyOne, keyTwo));
    }

    private static final class CacheKey {
        private final Key keyOne;
        private final Key keyTwo;

        CacheKey(Key keyOne, Key keyTwo) {
             this.keyOne = keyOne;
             this.keyTwo = keyTwo;
        }

        @Override
        public int hashCode() {
            int hash = keyOne == null ? 0 : keyOne.hashCode();
            return hash + 31 * keyTwo == null ? 0 : keyTwo.hashCode();
        }

        @Override
        public boolean equals(Object o) {
            // implementation omitted
        }
    }
}
于 2012-12-14T17:15:29.870 回答
0

我建议使用负载因子 1Map以所需大小备份自定义实现,ConcurrentHashMap并在内部有一个计数器,以确保您的包装ConcurrentHashMap不包含超过您希望它包含的内容。

于 2012-12-14T17:26:38.453 回答
0

您可以为这两个键维护两个 ConcurrentHashMaps,或者如果没有发生冲突的可能性则维护一个。要记住最旧的键,您可以维护一个队列,其中包含两个最旧的键,以便在达到缓存大小限制时删除。

于 2012-12-14T21:01:30.240 回答