我有一个带有私有静态映射的Java类,用于在执行应用程序期间存储信息。我只会将一次键/值放入Map中,但可以多次读取地图值。
所以我现在拥有它的方式,代码执行get并检查null。如果为null,那么我收集我需要的数据并将其放入地图中。客户端代码的后续调用将保证从映射中获取值。客户端不需要进行空检查。
这样做的原因是将数据放入地图可能很昂贵,所以我只想每个键执行一次。
这有什么模式吗?我似乎无法找到讨论这种情况的任何内容。
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;
}
}
答案 0 :(得分:3)
你最好的选择是ConcurrentHashMap,它是putIfAbsent方法。
您的实现不是线程安全的。为了使线程安全,声明字段final,将实现类更改为ConcurrentHashMap,这就足够了,如果您不关心有时值是否会被计算并存储多次(这种情况很少见:如果两个线程同时输入get和相应的值尚未计算。这通常是很好的权衡,因为通常最常见的情况是当您在缓存中有某些东西时。在这种情况下,您不使用任何额外的同步来检索现有值。)
如果要确保应用程序中存在至多一个给定键的值,您可以使用putIfAbsent而不是put来进一步扩展您的实现。
实现此目的的另一种方法是使用guava库: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中。
答案 1 :(得分:2)
checkout ConcurrentHashMap.putIfAbsent()
,它将提供您同步存储和检索所需的一切。
答案 2 :(得分:0)