同步容器。之前讲Java基础的时候,给大家讲过集合容器框架,比如大家熟知的Arraylist、LinkedLsit,它们都不是线程安全的。在多线程环境下,访问这些容器会导致并发安全问题。那么什么是同步容器,大家可以先简单了解下使用锁来实现同步的容器。主要的同步容器类有:VectorStackHashTableCollections.synchronizedXXX(组合方法)。这里简单介绍一下Vector。很简单,同样实现了List。接口,我们看一下它的add()和get()方法publicsynchronizedEget(intindex){if(index>=elementCount)thrownewArrayIndexOutOfBoundsException(index);返回元素数据(索引);}publicsynchronizedbooleanadd(Ee){modCount++;ensureCapacityHelper(elementCount+1);元素数据[元素计数++]=e;返回真;}Vector和Hashtable是线程安全的容器类,实现同步的方式是通过方法加锁(sychronized),这样读写都需要加锁操作,导致性能低下。并且即使是Vector这样线程安全的类,在面对多线程下的复合操作时,也需要通过客户端加锁来保证原子性。在场景中,为了提高容器的并发访问,我们经常使用并发容器。比如上一节提到的BlockingQueue,其实就是一种并发容器,比如CopyOnWrite容器。这里就不给大家过多介绍了,大家可以自行查看。我们要重点关注的是并发MapConcurrentMap接口publicinterfaceConcurrentMapextendsMap{//插入元素VputIfAbsent(Kkey,Vvalue);//移除元素booleanremove(Objectkey,Objectvalue);//替换元素booleanreplace(Kkey,VoldValue,VnewValue);//替换元素Vreplace(Kkey,Vvalue);}"putIfAbsent:"如果插入的key相同,则不会替换原来的keysomevalue;"remove:"增加对value的判断,如果要删除的key-value不能对应Map中原来的key-value,则不删除该元素;"replace(K,V,V):"增加了value值的判断。如果key-oldValue能对应到Map中原来的key-value,则进行替换操作;"replace(K,V):"与上面的replace不同,这个replace不会比较Map中原来的key-value,如果key存在则直接替换;ConcurrentHashMapConcurrentHashMap和HashMapJDK1.7一样也是基于哈希表的mapConcurrentHashMap在JDK1.7中提供了一种更细粒度的锁机制,以实现多线程下更高的性能,这种机制称为LockStriping。所提供的优势是在并发环境中将实现更高的吞吐量,而在单线程环境中性能损失很小。分段锁是指“将数据分段,并为每一段数据分配一个锁”。当一个线程占用锁访问一个段中的数据时,其他段中的数据也可以被其他线程访问。有些方法需要跨段,比如size(),isEmpty(),containsValue(),他们可能需要锁定整个表,而不是只锁定某个段,这需要依次锁定所有段,并依次释放操作完成后段锁ConcurrentHashMap由一个Segment数组结构和一个HashEntry数组结构组成。Segment是一个可重入锁ReentrantLock,HashEntry用于存储键值对数据。ConcurrentHashMap包含一个Segment数组。Segment的结构类似于HashMap的结构。它是一个数组和链表结构。一个Segment包含一个HashEntry数组。每个HashEntry都是链表结构的一个元素。每个Segment保护一个HashEntry数组。在修改HashEntry数组的数据时,必须先获取其对应的Segment锁。JDK1.8在JDK1.8中,ConcurrentHashMap主要做了两方面的优化:和HashMap一样,链表在长度达到8时也会转为红黑树,在出现大量冲突时可以提高查询效率;头节点(链表的头节点或红黑树的根节点)是一把锁,采用自旋+CAS避免不必要的锁开销,进一步提高并发性能。ConcurrentNavigableMap接口和ConcurrentSkipListMap类ConcurrentNavigableMap接口继承了NavigableMap接口。该接口提供了一种导航方法,该方法返回给定搜索目标的最接近匹配项。ConcurrentNavigableMap接口的主要实现类是ConcurrentSkipListMap类。从名字上看,它的底层使用的是跳表(SkipList)的数据结构。它是一种“以空间换时间”的数据结构,可以使用CAS保证并发安全。ConcurrentSetJDK提供了ConcurrentSkipListSet,它是一个线程安全的有序集合。底层使用ConcurrentSkipListMap实现。结语这一节主要给大家讲讲同步容器和并发容器。在并发容器中,你应该关注ConcurrentHashMap。这一节我就直接跟大家说说它的机制,听起来可能有点乱。