1.Hashtable和ConcurrentHashMap都是线程安全的Map集合
2.Hashtable并发度低,整个Hashtable对应一把锁,同一时刻,只能有一个线程操作它
3.jdk1.8之前ConcurrentHashMap使用Segment+数组+链表的结构,每个Segment对应一把锁,若多个线程访问不同的Segment,则不会冲突
4.jdk1.8开始ConcurrentHashMap将数组的每个头节点作为锁,若多个线程访问的头节点不同,则不会冲突,数组的容量决定了线程的并发,若容量为16允许则16个线程来并发访问。其结构参考了JDK8 HashMap的实现,采用了数组+链表+红黑树的实现方式来设计,内部大量采用CAS操作
Hashtable
public Hashtable(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal Load: "+loadFactor);
if (initialCapacity==0)
initialCapacity = 1;
this.loadFactor = loadFactor;
table = new Entry<?,?>[initialCapacity];
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}
protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] oldMap = table;
// overflow-conscious code
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE;
}
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
modCount++;
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap;
for (int i = oldCapacity ; i-- > 0 ;) {
for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next;
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}
1、底层为一个数组 hashtable entry[] 初始化大小是11
2、临界值是 8 约等于initialCapacity * loadFactor--->11*0.75 将entry里面的四个键值对 放入到table表中
3、扩容:rehash 数组容量(oldCapacity << 1) + 1 即:oldCapacity*2+1;