4

我有一个带有私有静态映射的 Java 类,用于在应用程序执行期间存储信息。我只会将一个键/值放入 M​​ap 中,但 Map 值可能会被读取多次。

所以我现在拥有它的方式,代码执行获取并检查是否为空。如果为空,那么我收集我需要的数据并将其放入地图中。客户端代码的后续调用将保证从映射中获取值。客户端不需要进行空值检查。

这样做的原因是,将数据放入地图可能会很昂贵,所以我只想对每个键执行一次。

这有什么模式吗?我似乎找不到任何讨论这种情况的东西。

TIA

这是一个完全非线程安全的示例:

public class TestWorm {

    private static Map<String, Object> map = new HashMap<String, Object>(32);

    public Object getValue(String key) {
        if (map.get(key) != null) {
            return map.get(key);
        }

        // do some process to get Object
        Object o = new Object();
        map.put(key, o);
        return o; 
    }
}
4

3 回答 3

3

你最好的选择是 ConcurrentHashMap ,它是 putIfAbsent 方法。

您的实现不是线程安全的。为了使其线程安全,声明字段 final,将实现类更改为 ConcurrentHashMap 就足够了,如果您不关心有时值是否会被计算和存储多次(这种情况很少见:如果两个线程同时进入 get 和尚未计算相应的值。这通常是一个很好的权衡,因为通常最常见的情况是缓存中有东西时。在这种情况下,您不使用任何额外的同步来检索现有值。)

如果您想确保应用程序中最多存在一个给定键的值,您可以通过使用 putIfAbsent 而不是 put 来进一步扩展您的实现。

实现这一点的另一种方法是使用番石榴库:http ://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/MapMaker.html

另一种方法是使用 ConcurrentHashMapV8 的 computeIfAbsent (http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/ConcurrentHashMapV8.java?view=markup)有一天会出现在 Java 8 中。

于 2012-04-14T10:14:18.710 回答
2

checkoutConcurrentHashMap.putIfAbsent()将为您提供同步存储和检索所需的一切。

于 2012-04-14T10:10:20.230 回答
0

这是典型的缓存模式。

例如Spring Framework 从 3.1 开始就提供了一个很好的 API

但是那里也有专门的框架,比如Ehcache

于 2012-04-14T10:17:42.750 回答