hashmap,hashtable,concurrenthashmap笔记

1、JDK1.7 HashMap 导致循环链表 (https://www.cnblogs.com/chanshuyi/p/java_collection_hashmap_17_infinite_loop.html)

1.7 的hashmap扩容复制的过程是对桶单个元素依次放入,新表的元素链通过前插法新增。两个线程同时resize,首线程导致原表的next改变,因为前插出现元素next指向了原链的前元素。一个线程没关系因为不会再用到。多线程的后线程resize时候用到就出现了环。会导致 HashMap Infinite Loop

2、jdk1.8 HashMap在扩容时保持了原来链表中的顺序,尾插法。不会发生1.7的循环链表

3、ConcurrentModificationException

Hashtable是线程安全的,它的方法是同步的,可以直接用在多线程环境中。而HashMap则不是线程安全的,在多线程环境中,需要手动实现同步机制。

Hashtable与HashMap另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。

4、ConcurrentHashMap

锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 

ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。

ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

5、ConcurrentModificationException

用迭代器遍历List时候,只要是涉及了改变ArrayList元素的个数的方法都会导致modCount的改变。所以我们这里可以初步判断由于expectedModCount 与modCount的改变不同步,导致两者之间不等,从而产生fail-fast机制

你可能感兴趣的:(java后端学习)