ConcurrentHashMap是JDK1.5并发包中提供的线程安全的HashMap的实现,其包结构关系如下:
public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable { } public abstract class AbstractMap<K,V> implements Map<K,V> { } public interface ConcurrentMap<K, V> extends Map<K, V> { }
ConcurrentHashMap实现并发是通过“锁分离”技术来实现的,也就是将锁拆分,不同的元素拥有不同的锁,ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,其中每一个片段是一个类似于HashMap的结构,它有一个HashEntry的数组,数组的每一项又是一个链表,通过HashEntry的next引用串联起来,它们有自己的锁。
final Segment<K,V>[] segments;
Segment继承自ReentrantLock,在创建Segment对象时,其所做的动作就是创建一个指定大小为cap的HashEntry对象数组,并基于数组的大小及loadFactor计算threshold的值:threshold = (int)(newTable.length * loadFactor);
Segment(int initialCapacity, float lf) { loadFactor = lf; setTable(HashEntry.<K,V>newArray(initialCapacity)); } void setTable(HashEntry<K,V>[] newTable) { threshold = (int)(newTable.length * loadFactor); table = newTable; }
构造函数
public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)创建一个带有指定初始容量、加载因子和并发级别的新的空映射。 参数: initialCapacity - 初始容量。该实现执行内部大小调整,以容纳这些元素。 loadFactor - 加载因子阈值,用来控制重新调整大小。在每 bin 中的平均元素数大于此阈值时,可能要重新调整大小。 concurrencyLevel - 当前更新线程的估计数。该实现将执行内部大小调整,以尽量容纳这些线程。 抛出: IllegalArgumentException - 如果初始容量为负,或者加载因子或 concurrencyLevel 为非正。 public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) { if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) throw new IllegalArgumentException(); if (concurrencyLevel > MAX_SEGMENTS) concurrencyLevel = MAX_SEGMENTS; // Find power-of-two sizes best matching arguments int sshift = 0; int ssize = 1; while (ssize < concurrencyLevel) { ++sshift; ssize <<= 1; } segmentShift = 32 - sshift; segmentMask = ssize - 1; this.segments = Segment.newArray(ssize); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; int c = initialCapacity / ssize; if (c * ssize < initialCapacity) ++c; int cap = 1; while (cap < c) cap <<= 1; for (int i = 0; i < this.segments.length; ++i) this.segments[i] = new Segment<K,V>(cap, loadFactor); }
基于如下方法计算ssize的大小:
int sshift = 0; int ssize = 1; while (ssize < concurrencyLevel) { ++sshift; ssize <<= 1; }
默认情况下构造函数的三个值分别为16、0.75f、16。在concurrencyLevel为16的情况下,计算出的ssize值为16,并使用该值作为参数传入Senment的newArray方法创建一个大小为16的Segment对象数组,也就是默认情况下ConcurrentHashMap是用了16个类似HashMap 的结构。
采用下面方法计算cap变量的值:
int c = initialCapacity / ssize; if (c * ssize < initialCapacity) ++c; int cap = 1; while (cap < c) cap <<= 1;
算出的cap为1。
put(Object key,Object value)方法
ConcurrentHashMap的put方法并没有加synchronized来保证线程同步,而是在Segment中实现同步,如下:
public V put(K key, V value) { if (value == null) throw new NullPointerException(); int hash = hash(key.hashCode()); return segmentFor(hash).put(key, hash, value, false); } //下面为Segment的put方法 V put(K key, int hash, V value, boolean onlyIfAbsent) { lock(); try { int c = count; if (c++ > threshold) // ensure capacity rehash(); HashEntry<K,V>[] tab = table; int index = hash & (tab.length - 1); HashEntry<K,V> first = tab[index]; HashEntry<K,V> e = first; while (e != null && (e.hash != hash || !key.equals(e.key))) e = e.next; V oldValue; if (e != null) { oldValue = e.value; if (!onlyIfAbsent) e.value = value; } else { oldValue = null; ++modCount; tab[index] = new HashEntry<K,V>(key, hash, first, value); count = c; // write-volatile } return oldValue; } finally { unlock(); } }ConcurrentHashMap不能保存value为null值,否则抛出NullPointerException,key也不能为空:
int hash = hash(key.hashCode());在HashMap中,null可以作为key也可以为value。和HashMap一样,首先对key.hashCode()进行hash操作,得到key的hash值,然后再根据hash值得到其对应数组的Segment对象,接着调用Segment对象的put方法来完成操作。当调用Segment对象的put方法时,先进行lock操作,接着判断当前存储的对象个数加1后是否大于threshold,如大于则将当前的HashEntry对象数组大小扩大两倍,并将之前存储的对象重新hash转移到新的对象数组中。接下去的动作和HashMap基本一样,通过对hash值和对象数组大小减1进行按位与操作后,找到当前key要存放的数组的位置,接着寻找对应位置上的HashEntry对象链表是否有key、hash值和当前key相同的,如果有则覆盖其value,如果没有则创建一个新的HashEntry对象,赋值给对应位置的数组对象,构成链表。
相关推荐
在深入学习Java并发集合时,我们需要理解每个类的内部实现机制,如ConcurrentHashMap的分段锁,CopyOnWriteArrayList的写时复制策略,以及各种同步工具类的工作原理。同时,了解何时以及如何选择合适的并发集合也是...
5. **并发集合**:Java的并发集合类库,如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等,为并发环境下高效、安全的数据共享提供了支持。 6. **原子操作与CAS**:AtomicInteger、AtomicLong等...
ConcurrentHashMap使用了分段锁(Segment)来实现并发的读写操作,每个Segment都相当于一个小的HashMap,将...因此,如果需要保证精确的操作顺序或避免并发更新带来的问题,可以考虑使用更高级的同步工具或并发集合类。
随着章节的深入,作者可能会更深入地讲解Java提供的并发工具,例如锁、原子变量、线程池、以及并发集合等高级特性。 在深入理解这些并发工具的基础上,读者可以学习到如何安全地共享数据,避免多线程之间的数据竞争...
Java语言提供了丰富的并发工具和API,如线程、守护线程、线程池、同步机制(synchronized、wait/notify)、并发集合(ConcurrentHashMap、CopyOnWriteArrayList等)以及并发框架(ExecutorService、Future、Callable...
Java 并发集合:ConcurrentHashMap 和 BlockingQueue Java 并发集合是 Java 语言中的一种高级hread-safe 集合框架,用于在多线程环境中实现高效、安全的数据存储和访问。其中,ConcurrentHashMap 和 BlockingQueue ...
并发集合是Java并发编程中的重要组成部分,如`ConcurrentHashMap`, `CopyOnWriteArrayList`, `ConcurrentLinkedQueue`等,它们设计为线程安全,能够在并发环境中高效地工作。书中的章节可能会详细解释这些集合的设计...
以上知识点覆盖了Java并发编程的主要方面,包括线程管理、同步机制、并发工具、设计模式、并发集合以及并发编程的最佳实践等,是理解和掌握Java并发编程的关键。在实际开发中,理解和熟练运用这些知识可以编写出高效...
最后,书中还涵盖了并发集合框架,如`ConcurrentHashMap`,它在并发环境下提供了高效且线程安全的存储解决方案。还有`CopyOnWriteArrayList`和`CopyOnWriteArraySet`,它们在读多写少的场景下表现出色。 总之,...
- **并发集合**:详细介绍Java提供的各种并发集合类,如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,并讨论它们适用的场景和优缺点。 #### 四、案例分析 书中通过大量的实际案例分析,帮助读者更好地理解并发...
【Java并发集合之ConcurrentHashMap详解】 在Java的并发编程中,`ConcurrentHashMap`是一个极其重要的工具,它是线程安全的哈希映射表,提供了高效且安全的并发访问性能。相较于传统的线程安全的`Hashtable`和非...
Java并发集合,如ConcurrentHashMap、CopyOnWriteArrayList等,设计时考虑了并发性能,能够在不加锁的情况下提供线程安全的访问。这些集合内部实现了复杂的同步策略,提高了并发效率。 并发工具类,如...
5. **并发集合**: - **线程安全的集合**:如Vector、ConcurrentHashMap和CopyOnWriteArrayList等,它们在内部实现了同步机制,保证了并发访问的安全性。 - **并发容器框架**:如BlockingQueue(阻塞队列),常...
此外,书中还介绍了Java并发容器,如ConcurrentHashMap、CopyOnWriteArrayList和BlockingQueue等,这些都是为并发环境设计的高效数据结构。它们在多线程环境下的性能和线程安全特性使得开发者能更方便地实现并发操作...
- **并发集合** 如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,它们在内部实现了线程安全的算法,可以在并发环境中高效使用。 7. **活锁与死锁** - **活锁** 发生在线程间不断地尝试但无法取得进展的情况,...
4. **并发集合**:Java并发包提供了线程安全的集合实现,如ConcurrentHashMap、CopyOnWriteArrayList和BlockingQueue等。这些集合在多线程环境中能保证数据一致性。 5. **死锁、活锁和饥饿**:文档可能会介绍这些...
4. **并发集合**:Java并发集合如`ConcurrentHashMap`、`CopyOnWriteArrayList`和`ConcurrentLinkedQueue`等,是为并发环境优化过的数据结构。它们内部实现了线程安全,能够在不引入全局锁的情况下实现高效并发操作...
此外,Java并发集合框架是另一个重要章节。它包含一系列优化过的线程安全容器,如ConcurrentHashMap、CopyOnWriteArrayList等,这些容器提供了高效且线程安全的并发操作。了解它们的工作原理和使用场景对于编写高...