天天看点

线程安全的集合

集合接口:

注意:本文的扩容是指当超出一定的容量,将原来的值都得Copy到新的空间

List:有序可重复

Set:无序不可重复

map:键值对

实现list接口的有ArrayList,LinkedList,Vector

ArrayList:底层是以数组的形式来存储数据的,初始容量为10,当超过数组长度是;进行扩容,扩容容量为(原来的容量)*1.5+1,线程不安全;

LinkedList:底层是链表,动态,不安全

Vector:底层以数组的形式来存储数据,初始容量10,当超出一个时,开始进行扩容,扩充容量为原来容量的2倍,是线程安全的,每一个方法的实现都进行了syn操作,所以会导致效率比较低;

实现set接口的有HashSet,sortedSet...

hashset:线程不安全,初始容量为16,加载因子为0.75,扩充容量为(原来的容量)*2;

Map:实现Map接口的为HashMap、

HashMap:线程不安全,底层是一个散列表(数组和链表的结合):初始容量16,加载因子0.75,扩充容量为(原来的容量)*2

在实现时有必要重写hashcode和equels方法:因为在进行put操作的时候会根据添加对象的hashcode来查找该对象应该属于哪条链表,再进行相应的操作,在jdk1.8,对散列表进行了一些优化,当链表节点大于8时,为了避免链表成环,将转换成为红黑树。

TableMap:线程安全,每个方法加了syn.同样,这样会导致效率低下

在java.util.concurrent包下面提供了很多线程安全的集合:

concurrentHashMap:使用了分段锁,在一定程度上避免了没锁带来的不安全性,也避免了全局加锁带来的底性能;

CopyOnWriteArrayList:线程安全,利于多读少写的场景

ConcurrentLinkedQueue;

BlockingQueue

ConcurrentSkipListMap

还可以使用Collections.synchronizedMap(new HashMap());等方法,这里它是使用了一个委托,将自己的Map相关的功能交给传入的HashMap来实现。

继续阅读