并发编程(十五):并发容器

【关于作者】

关于作者,目前在蚂蚁金服搬砖任职,在支付宝营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(https://0522-isniceday.top/)联系我

1.同步容器

同步容器,指的是通过synchronized关键字来保证原子性,类似如下的包装类都是基于此考量:

ArrayList、HashSet 和 HashMap 包装成了线程安全的 List、Set 和 Map。

List list = Collections.
  synchronizedList(new ArrayList());
Set set = Collections.
  synchronizedSet(new HashSet());
Map map = Collections.
  synchronizedMap(new HashMap());

但是针对包装后的容器采用迭代器遍历,还是会存在原子性的问题,因此这种场景也可以进行synchronized进行包装

List list = Collections.
  synchronizedList(new ArrayList());
synchronized (list) {  
  Iterator i = list.iterator(); 
  while (i.hasNext())
    foo(i.next());
}    

Java 提供的同步容器还有 Vector、Stack 和 Hashtable,这三个容器不是基于包装类实现的,但同样是基于 synchronized 实现的,对这三个容器的遍历,同样要加锁保证互斥

2.并发容器

Java1.5之前都是通过同步容器实现线程安全,但是使用synchronized串行度太大了,性能太差。JDK1.5之后提供了性能更高的容器,称之为并发容器

image-20210816170617616

1.1.List

List只有一个实现类:CopyOnWriteArrayList

其采取的机制其实就是写时复制(CopyOnWrite)机制,读操作的时候不进行处理,写操作的时候复制数组并在复制的数组执行写操作,最后将数据的引用指向新的数组

image-20210816172935851 image-20210816172944273

需要注意的几个地方:

  1. 数据会存在短暂的不一致,写入的新元素无法立即被读取到
  2. CopyOnWriteArrayList 迭代器是只读的,不支持增删改。因为迭代器遍历的仅仅是一个快照,而对快照进行增删改是没有意义的

1.2.Map

Map接口的两个实现主要是:ConcurrentHashMap、ConcurrentSkipListMap。它们从应用的角度来看,主要区别在于ConcurrentHashMap 的 key 是无序的,而 ConcurrentSkipListMap 的 key 是有序的

image-20210816174536939

1.3.Set

Set 接口的两个实现是 CopyOnWriteArraySet 和 ConcurrentSkipListSet,使用场景可以参考前面讲述的 CopyOnWriteArrayList 和 ConcurrentSkipListMap

1.4.Queue

可以按照两个维度针对队列进行分类:

  1. 阻塞或非阻塞,所谓阻塞是指队满时,入队操作阻塞。队空时,出队操作阻塞。阻塞队列都用 Blocking 关键字标识
  2. 单端或双端队列,单端是只允许一段出队或入队,双端是允许双端进行入队出队操作,单端队列使用 Queue 标识,双端队列使用 Deque 标识

此时可将Queue分为如下四大类:

  1. 单端阻塞队列:其包括ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、LinkedTransferQueue、PriorityBlockingQueue 和 DelayQueue。内部一般会持有一个队列结构,其实现包括数组,例如ArrayBlockQueue,或链表,例如LinkedBlockQueue。甚至还可以不持有队列,例如SynchronousQueue,此时生产者的入队操作必须等待消费者的出队操作。而 LinkedTransferQueue 融合 LinkedBlockingQueue 和 SynchronousQueue 的功能,性能比 LinkedBlockingQueue 更好。PriorityBlockQueue支持按照优先级出队(其实现是一个二叉堆),DelayQueue支持延时出队。
  2. 双端阻塞队列:其包括LinkedBlockDeque
  3. 单端非阻塞队列:其包括ConcurrentLinkedQueue
  4. 双端非阻塞队列:其实现是 ConcurrentLinkedDeque

只有 ArrayBlockingQueue 和 LinkedBlockingQueue 是支持有界的,所以在使用其他无界队列时,一定要充分考虑是否存在导致 OOM 的隐患

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈哈张大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值