`
san_yun
  • 浏览: 2594875 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

ConcurrentHashMap的putIfAbsent总结

 
阅读更多

最近在设计一个可缓存的类,发现putIfAbsent使用还是有些坑要注意的,总结一下。之前的代码如下

	private static ConcurrentHashMap<String, Pattern> compliedPattern = new ConcurrentHashMap<String, Pattern>();

	public static Pattern getPattern(String pattern) {
		return compliedPattern.putIfAbsent(pattern, Pattern.compile(pattern));
	}

 之前以为这样一行代码就完美了,结果测试每次都返回null,查看api看到文档:

写道
public V putIfAbsent(K key,
V value)

如果指定键已经不再与某个值相关联,则将它与给定值关联。这等价于:

if (!map.containsKey(key))
return map.put(key, value);
else
return map.get(key);

除了原子地执行此操作之外。

指定者:
接口 ConcurrentMap<K,V> 中的 putIfAbsent

参数:
key - 与指定值相关联的键
value - 与指定键相关联的值
返回:
以前与指定键相关联的值,如果该键没有映射关系,则返回 null
抛出:
NullPointerException - 如果指定键或值为 null

 

这个意思是如果key不存在必然返回null,因为put方法返回的value是之前有映射的value。那么改成这样如何?

public static Pattern getPattern(String pattern) {
		Pattern p = Pattern.compile(pattern);
		Pattern ret = compliedPattern.putIfAbsent(pattern, p);
		if (ret == null) {
			return ret;
		} else {
			return p;
		}
	}

 但这样还搞个毛的缓存啊,每次都会compile了。正确的解法是:

	public static Pattern getPattern(String pattern) {
		Pattern ret = compliedPattern.get(pattern);
		if (ret == null) {
			Pattern newPattern = Pattern.compile(pattern);
			ret = compliedPattern.putIfAbsent(pattern, Pattern.compile(pattern));
			if (ret == null) {
				ret = newPattern;
			}
		}
		return ret;
	}

 参考:

http://stackoverflow.com/questions/3752194/best-practice-to-use-concurrentmaps-putifabsent

http://stackoverflow.com/questions/10743622/concurrenthashmap-avoid-extra-object-creation-with-putifabsent

http://en.wikipedia.org/wiki/Double-checked_locking

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics