- 关于 Collections.synchronizedList(List) 等一系列构建出来线程安全的List、Set、Map均为包装了一个基本的List、Set、Map上的读写操作方法上增加了synchronized锁(不管get、put、add等操作均加上了synchronized)
- 而Jdk的java.util.concurrent提供了高性能的一系列的线程安全的数据结构
常用线程安全的数据结构 :
- CopyOnWriteArrayList : get方法无锁,add方法:每次都copy出1个副本,并且利用ReentrantLock加上了锁,所以add方法的性能是比较低的
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; //这里会进行数组的整体复制 Object[] newElements = Arrays.copyOf(elements, len + 1); //修改副本 newElements[len] = e; //将副本设置回来 setArray(newElements); return true; } finally { //释放锁 lock.unlock(); } }
结论: 在读多写少的高并发环境中,使用CopyOnWriteArrayList 可以提高系统的性能;但是在写多读少的场合,CopyOnWriteArrayList 的性能还不如Vector。 - CopyOnWriteArraySet : 内部实现完全依赖于CopyOnWriteArrayList
- ConcurrentHashMap : 专门为线程并发而设计的HashMap,get()操作是无锁的,而put()操作的锁粒度又小于synchronized的HashMap,因此整体性能优于synchronized的HashMap。
- 并发Queue: JDK提供2套实现(两着都继承自Queue接口):
(1) : ConcurrentLinkedQueue为代表的高性能队列
场景: 适用于高并发场景下的队列,通过无锁的方式实现高并发下的高性能,ConcurrentLinkedQueue的性能要好于BlockingQueue。
(2) : BlockingQueue接口为代表的阻塞队列;
场景:BlockingQueue并不是在于提升高并发时的队列性能,而是在于简化多线程间的数据共享。主要用于生产者-消费者模式中。读写阻塞。主要有ArrayBlockingQueue和LinkedBlockingQueue。
5. 并发Deque(双端队列): 具体可以参考JDK源码。LinkedList,ArrayDeque,LinedBlockingDeque均实现了Deque接口。