Java多线程之线程安全策略---并发容器
一、并发容器JUC(java.util.concurrent)
并发容器里面提供的线程安全的集合和map。
ArrayList--->CopyOnWriteArrayList
HashSet--->CopyOnWriteArraySet
TreeSet--->ConcurrentSkipListSet
HashMap--->ConcurrentHashMap
TreeMap--->ConcurrentSkipListMap
二、CopyOnWriteArrayList
CopyOnWriteArrayList:当有新元素添加到CopyOnWriteArrayList时,先从原有的数组里面copy一份出来,然后在新的数组上进行写操作,写完之后再将原来的数组指向新的数组。CopyOnWriteArrayList的add操作是在锁的保护下进行的,避免在多线程并发做add操作时复制出多个数组出来。
缺点:1.由于在写操作时要拷贝数组,就会消耗内存。2.不能用于实时读的场景,拷贝数组,新增元素都需要时间。
更适合读多写少的场景。
CopyOnWriteArrayList设计思想是1.读写分离,2.数据最终一致性,3.使用时另外开辟空间,解决并发冲突。
CopyOnWriteArrayList读操作都是在原数组上读的。
CopyOnWriteArrayList的add方法:
可以看到是加了锁进行的操作。
三、CopyOnWriteArraySet、ConcurrentSkipListSet
HashSet对应的并发容器里的线程安全的类是CopyOnWriteArraySet.
TreeSet对应的是ConcurrentSkipListSet。
ConcurrentSkipListSet和TreeSet一样,支持自然排序,是基于map集合的,add,remove都是线程安全的,但是对于批量操作,比如addAll,removeAll,containsAll不能保证原子方式执行,因为它们底层还是调用add,remove,contains方法。
四、ConcurrentHashMap、ConcurrentSkipListMap
ConcurrentHashMap是HashMap线程安全的版本,不允许空值,在实际操作中,除了少数的插入,删除操作外,绝大多数使用Map都是读操作。
ConcurrentSkipListMap是TreeMap的线程安全的版本,内部是通过SkipList这种跳表的方式实现的。
ConcurrentHashMap 、ConcurrentSkipListMap比较:
1. ConcurrentHashMap 比ConcurrentSkipListMap性能好
2. ConcurrentSkipListMap的key是有序的,支持更好的并发,存取时间和线程数没有关系,也就是说在数据量一样的情况下,并发的线程越多,ConcurrentSkipListMap越可以体现处优势。