6.9并发容器

并发容器中,线程安全的集合和map

  • ArrayList → CopyOnWriteArrayList

    写操作时复制。当有新元素添加到CopyOnWriteArrayList时,从原数组上拷贝一份副本,在副本上做写操作,完成写操作后,将原来的数组指向副本。

    注意:CopyOnWriteArrayList都是在加锁的情况下进行写操作,以避免多线程时出现多个副本,把数组搞乱了。

CopyOnWriteArrayList的缺点:

  • 写操作时需要拷贝数组,占用内存,当数组数据较多时,可能出现 young GC或full GC

  • 不能用于实时的的场景,由于copy出副本、新添加元素都需要时间,读取时的数据可能是旧的,虽然CopyOnWriteArrayList能做到最终的一致性,但没法满足实时性的要求

CopyOnWriteArrayList更适合读多写少的场景

CopyOnWriteArrayList读操作时都是在原数组上读的,不需要加锁,而写操作要加锁,避免多个线程并发修改时复制出多个副本

  • HashSet、TreeSet → CopyOnWriteArraySet、ConcurrentSkipListSet

    CopyOnWriteArraySet是基于CopyOnWriteArrayList实现的,适合于很小的集合,只读操作大于写入操作的场景。

    ConcurrentSkipListSet JDK6新增的类,很TreeSet一样,支持自然排序,可以在构造的时候自定义比较器,和其他Set一样,ConcurrentSkipListSet是基于Map集合的。对于contains()、add()、remove()方法都是线程安全的,但是对于批量操作,比如containsAll()、addAll()、removeAll()并不能保证以原子方式执行。ConcurrentSkipListSet 是能使用空元素的,即NULL

请自行编写代码验证线程安全性

  • HashMap、TreeMap → ConcurrentHashMap、ConcurrentSkipListMap

    ConcurrentHashMap不运行空值,ConcurrentHashMap对读读操作进行了大量的优化,具有特别高的并发性。

    ConcurrentSkipListMap基于SkipList这种跳表的结构实现的

ConcurrentHashMap与ConcurrentSkipListMap对比

根据实验,4个线程,1.6万数据的情况下,ConcurrentHashMap的存取速度是ConcurrentSkipListMap的4倍左右

ConcurrentSkipListMap的key是有序的

ConcurrentSkipListMap支持更高的并发,存取时间和线程数是几乎没有关系的,即数据量一定的情况下,线程数越多,越能体现出ConcurrentSkipListMap的优势

请自行编写代码验证线程安全性

Last updated

Was this helpful?