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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值