同步类容器都是线程安全的,但是在有时候需要加锁来保护复合操作,比如:迭代(反复访问容器中的元素),跳转(根据指定顺序找到当前元素的下一个),条件运算,有时候并发操作,可能会引起意外。比如ConcurrentModificationException异常(迭代集合元素时候,并发修改)。
同步类容器有:vector HashTable,底层都是采用synchronized进行同步的。
注意可以采用如下方式使得容器同步:
Map<String,String > map=Collections.synchronizedMap(new HashMap<String,String>());
同步类容器虽然线程安全,但是他们的状态都是串行化,严重降低了性能。
而并发类容器则是专门针对并发设计的使用ConcurrentMap代替传统的hashTable,使用CopyOnWriteArrayList代替了传统的vector,还有并发的CopyOnWriteArraySet,以及并发的Queue,ConcurrentLinkedQueue(高性能队列),LinkedBlockingQueue(阻塞队列)。
ConcurrentMap接口有如下两个重要实现:
ConcurrentHashMap和ConcurrentSkipListMap(支持并发排序功能)
支持并发的原理:ConcurrentHashMap内部采用段来表示这些不同的部分,每个段实际上就是一个HashMap,他们有自己的锁,只要不同的操作发生在不同的段上,就可以并发执行,一共把一个整体分成了16段,也就是说最高支持16个线程并发操作容器,这是一种通过减小锁粒度的办法来降低锁的竞争的方案,并且代码中大多共享变量使用volatile关键字声明,目的是第一时间获取修改内容,性能非常好。
package com.wuk.thread;
import java.util.concurrent.ConcurrentHashMap;
public class MyThread04 {
private static ConcurrentHashMap chMap=new ConcurrentHashMap();
public static void main(String[] args) {
chMap.put("k1", "v1");
chMap.put("k2", "v2");
chMap.put("k3", "v3");
chMap.put("k4", "v4");
chMap.put("k5", "v5");
chMap.putIfAbsent("k1", "1111");//如果存在不插入
}
}
简称COW,COW容器有两种:CopyOnWriteArrayList和CopyOnWriteArraySet。
CopyOnWrite的理解:
CopyOnWrite容器也就是写时复制的容器,即当我们往一个容器中添加元素时候,不直接往当前容器添加,而是先将当前容器进行复制,然后往新的容器里添加元素,添加之后,将原容器的引用指向新的容器,这样的好处是我们可以对CopyOnWrite容器进行并发的读写操作,而不需要加任何锁,这就是一种读写分离的容器。
但是记住这种适合于读多写少的场合,因为复制一个容器比较浪费资源和时间。
注意如果出现多个线程写的情况下,就会采用等待的方式,看看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();
}
}
ReentrantLock 重入锁
lock.lock();加锁
lock.unlock(); 释放锁