Java中关于多线程Map的非空存储(ConcurrentHashMap)
在日常开发中Map可能是Java集合框架中最常用的一个类了,当我们常规使用HashMap时可能会经常看到以下这种代码:
Map<Integer, String> hashMap = new HashMap<>();
hashMap.put(user.getId,user.getUsername);
似乎看起来并没有什么问题,但当你用到多线程的场景时,HashMap
必然是线程不安全的, java.util原始提供的多线程map是使用Synchronized
同步锁实现线程安全的HashTable,但是由于锁是针对整个map来说的,效率低下,为了更高的支持高并发,JDK1.5以后Java提供了另一个线程安全的HashMap
,即ConcurrentHashMap
采用分段锁的方法实现线程安全,同时线程安全的map也提供了一个坑,与HashMap
在使用上最浅显的不同是,前者不支持空字段存储,所以当你再使用上述代码去使用HashTable
或者ConcurrentHashMap
时就容易抛出空指针异常,需要做的就是在进行put()
操作之前先对对象进行字段是否为空的判断。
在Map中关于K/V是否为空的说明如下
集合类 | Key | Value | Super | 说明 |
---|---|---|---|---|
Hashtable | 不允许为 null | 不允许为 null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为 null | 不允许为 null | AbstractMap | 分段锁技术 |
TreeMap | 不允许为 null | 允许为 null | AbstractMap | 线程不安全 |
HashMap | 允许为 null | 允许为 null | AbstractMap | 线程不安全 |