1.常用集合类
- 在并发场景中,传统的集合类在写操作时很容易出现
java.util.ConcurrentModificationException 并发修改异常
,因此在JUC中引出了很多的集合类 - 对于传统的集合类,其实也有一些解决并发的方案,但是效率是远不如JUC包下的类,比如对于ArrayList可以用
Vector
、封装一层Synchronized
、(JU包下的)Collections.synchronizedList(new ArrayList<>())
来代替,当然这些方案效率是不如JUC下的CopyOnWriteArrayList
1.1CopyOnWriteArrayList
这个是用来替换ArrayList的
使用方法如下:
new CopyOnWriteArrayList<>(new ArrayList<>());
或者new CopyOnWriteArrayList<>();
1.1.1COW
- CopyOnWrite 写入时复制 COW 计算机程序设计领域的一种优化策略(空间换时间)
- 使用ReentrantLock保证并发、每次写入都copy底层数组、volatile修饰这个数组——》保证最终一致性
1.2.1源码分析
add需要加锁
get是直接从数组中读取
防止指令重排,配合锁机制可以实现读写冲突时的最终一致性
1.2CopyOnWriteArraySet
- 用来在并发场景下代替HashMap,且性能优于
Collections.synchronizedSet(new HashSet<>());
- 与HashSet的底层是HashMap不同,JUC下的这个Set底层是List
1.2.1源码分析
由源码可知,其底层仍然使用的是CopyOnWriteArrayList
,难怪这个Set叫ArraySet。。
添加时需要先判断是否存在,这里时间复杂度明显高于HashSet的O(1)
1.3ConcurrentHashMap
HashMap的并发解决方案,二者都继承于AbstractMap
且ConcurrentMap
也继承于Map
,即证明二者大题相同,但既然是保证了并发,应该从添加元素的逻辑找出区别
2.常用辅助类
2.1CountDownLatch
- new的时候指定大小
await()
阻塞直到计数器归零- 每次有线程调用
countDown()
数量-1
await()
方法,与ConditionObject
差不多,调用的都是AQS
中的方法
2.2CyclicBarrier
这个和上面的不一样,这个是:
- CyclicBarrier 字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要做的事情是让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时候,屏障才会开门。所有被屏障拦截的线程才会运行。
CountDownLatch
是阻塞直到计数器归零,CyclicBarrier
是累加到某一个值的时候触发- 写法也不一样,
CyclicBarrier
可以在第二个参数添加一个Runnable
await()到3次之后触发,并且所有调用的线程解除阻塞
2.3Semaphore
可以做一个限流策略,由两个参数:阈值 和 是否公平