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

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

 

分享到:
评论

相关推荐

    JDK1.8中ConcurrentHashMap中computeIfAbsent死循环bug问题

    这个问题的解决方案是使用JDK1.8中ConcurrentHashMap的另一个方法,即putIfAbsent方法。putIfAbsent方法可以在键不存在时,提供一个默认值作为回应。但是,putIfAbsent方法不具备computeIfAbsent方法的功能,它不能...

    java7-8中的 HashMap和ConcurrentHashMap全解析

    `ConcurrentHashMap`提供了多种线程安全的操作,如`putIfAbsent()`, `remove()`, `replace()`等,这些方法在并发环境下可以确保操作的原子性。同时,`ConcurrentHashMap`还支持弱一致性迭代器,这意味着在迭代过程中...

    java 使用ConcurrentHashMap和计数器实现锁

    当线程需要获取锁时,程序会使用 ConcurrentHashMap 的 putIfAbsent 方法来检查锁是否已经存在,如果不存在,则创建一个新的锁对象,并将其存储在 ConcurrentHashMap 中。然后,程序会使用计数器来记录锁的状态,...

    Java 中ConcurrentHashMap的实现

    6. **原子性操作**:`ConcurrentHashMap`提供了诸如`putIfAbsent()`这样的原子操作,确保在插入元素时,如果键不存在,可以安全地插入,而不会因并发问题导致数据冲突。 在决定何时使用`ConcurrentHashMap`时,应...

    ConcurrentHashSet-main-源码.rar

    添加元素时,`add`方法会调用`ConcurrentHashMap`的`putIfAbsent`,如果元素不存在则插入,否则不做任何处理,确保元素的唯一性。删除元素则使用`remove`方法,通过`key-value`键值对中的`value`为`null`来实现。...

    java多线程并发及集合框架面试题

    此外,ConcurrentHashMap 还提供了其他高级特性,如支持原子操作的 putIfAbsent()、remove() 和 replace() 方法,这些方法能够在不使用额外同步的情况下保证操作的原子性。这些特性使得在并发编程中更易于保证数据的...

    java并发集合

    例如,查看ConcurrentHashMap的putIfAbsent()方法是如何实现线程安全的,或者研究CopyOnWriteArrayList是如何通过复制数组实现并发安全的。 在实际开发中,熟练运用这些并发集合能够帮助我们编写出更加高效、可靠的...

    大并发编程交流

    - **ConcurrentHashMap 的 putIfAbsent 方法**:这个方法可以原子地检查并插入键值对,如果键已经存在则不会插入新的值,这样可以减少不必要的锁操作。 - **使用 FutureTask 实现延迟加载**:通过将任务封装到 `...

    java的一些基础知识什么这类的

    Java 基础知识点总结 一、String 不可变性 * String 的不可变性来自于它的实现方式,String 的值被存储在一个字符数组中,并且该数组被声明为 final,无法被修改。 * 不可变性使得 String 可以被安全地共享和缓存...

    Java并发程序设计教程

    `ConcurrentHashMap.putIfAbsent`和`CopyOnWriteArrayList`等容器利用了无锁机制,可以在高并发下保持高性能。 #### 六、关于锁使用的经验介绍 深入理解锁的使用,如公平锁与非公平锁、重入锁等概念,可以帮助...

    Java-concurrentMap-内存模型深入分析-HotCode

    在`concurrentMap`的实现中,HotCode可能涉及到并发操作的关键路径,如putIfAbsent、getOrCompute等。通过分析这些热点代码,我们可以找到性能瓶颈并进行针对性优化,比如使用更高效的并发数据结构或算法。 `Java ...

    针对于java面试资料.docx

    - **原子操作**:`ConcurrentHashMap` 提供了如 `putIfAbsent`、`remove` 和 `replace` 等原子操作方法,在保持线程安全的同时提供更高的性能。 #### 二、ThreadLocal 的作用与原理 **定义:** `ThreadLocal` 是 ...

    Spring系列.docx

    this.singletonObjects.putIfAbsent(beanName, singletonObject); } catch (Exception ex) { // ... } } return singletonObject; } ``` 总的来说,Spring通过IoC和工厂模式实现了对bean的高效管理,通过单例...

    Java开发程序设计教程

    无锁编程(Lock-free)是一种实现并发程序设计的技术,它避免使用传统的锁机制,而是通过原子操作(如java.util.concurrent.atomic包下的类)和无锁数据结构(如ConcurrentHashMap的putIfAbsent方法和...

    java多线程编程实践

    - **一致性操作**:`ConcurrentHashMap`还提供了一些一致性操作方法,如`putIfAbsent`、`remove`、`replace`等,这些方法能够在保证数据一致性的同时,避免不必要的更新操作。 ##### 1.2 `BlockingQueue` `...

    JavaCachingwithGuava

    总结来说,Guava 提供了强大的缓存支持,特别是通过 `LoadingCache` 和 `CacheLoader` 的组合,能够轻松实现高效、线程安全的缓存功能。此外,Guava 还考虑到了异常处理等问题,使得开发者能够更加专注于业务逻辑的...

    JDK7api JDKAPI

    2. **`ConcurrentHashMap`的改进**:JDK7中的`ConcurrentHashMap`在并发性能上有了显著提升,提供了更细粒度的锁,减少了锁竞争。 五、其他特性 1. **钻石运算符**:在创建匿名内部类或泛型实例时,可以省略类型...

    hashMap和hashTable的区别

    - **HashMap**:提供了 `containsKey`, `containsValue`, `putIfAbsent` 等方法。 - **HashTable**:提供了 `contains` 方法来判断是否存在某个值(已过时),而 `containsKey` 和 `containsValue` 是 `Map` 接口...

    Concurrent In java

    `ConcurrentHashMap`还提供了一系列一致性操作方法,如`putIfAbsent`、`remove`、`replace`等,这些方法可以在确保数据一致性的前提下高效地更新数据。 ##### 1.2 BlockingQueue `BlockingQueue`是一个线程安全的...

Global site tag (gtag.js) - Google Analytics