并发容器介绍

一、概述

JUC中比较有代表性的并发容器

二、ConcurrentHashMap

高并发情况下可以用的Map,HashMap不是线程安全的。HashTable,即线程安全又拥有Map的能力,但是他的实现是给每一个方法加上synchronized锁,效率低。所以可以选择concurrentHashMap。

1.7和1.8的区别:

jdk 1.7中是基于segment数组然后通过ReentrantLock对每一个segment元素加锁,来保证每一个segment内线程操作的安全性,从而保证了所有线程的操作安全;其中:默认的segment数组长度是16,也就是说concurrenthashmap1.7默认的并发度是16;

1.8中直接取消segment数组,采用和hashmap相同的结构 :Node数组+链表+红黑树;每一次增加操作是锁住一个Node元素,相对于1.7中是锁住一个segment,1.8的锁粒度要小一些(因为segment中是hashentry数组);引入红黑树的原因与hashmap的原因一样,当每一个Node下面有很多元素,链表过长的时候,访问的效率会变低,引入红黑树来使其查询操作的复杂度为logN

源码:

put(key,value)

  1. 如果table数组为null或者长度为0,则初始化一个长度为16的空的Node数组

  2. 如果目标位置为空,直接cas赋值

  3. 如果遇到扩容(即即将插入位置的元素hash值为-1),调用helpTransfer(tab,f)一起扩容。

  4. 如果存在哈希冲突,往链表或者红黑树里插入元素,链表长度大于9,判断数组长度大于64转成红黑树

如何统计数组的长度:

ConcurrentHashMap⾥总的kv数量就是:【baseCount数量】+ 【sum(CounterCells⾥所有CounterCell的value)】

basecount只有在多线程都进行相加,唯独只有一个线程抢占到了cas成功的才进行baseCount+,其他抢占失败的都会进入到countercells中进行相加。

三、ConcurrentLinkedQueue

非阻塞队列,使用循环CAS算法实现。是一个基于链接节点的无界线程安全的队列,按照先进先出原则对元素进行排序。新元素从队列尾部插入,而获取队列元素,则需要从队列头部获取。

构造函数创建了一个空节点作为构造函数第一个Node节点,底层由单向链表组成。高并发环境中性能最好的队列。入列出列线程安全,遍历不安全。不允许添加null元素

add:对tail的更新是会产⽣滞后的,也就是每次更新都会跳跃两个元素。这 么做的⽬的,就是为了减少cas操作的次数

remove:

哨兵:

四、CopyOnWriteArrayList

读操作不加锁,写操作也不会阻塞读,写入操作时,进行一次自我复制,产生一个副本,写操作就在副本中执行,写完之后,再将副本替换原来的数据。

  • get(int index):从数组中获取对应下标的元素,因为读操作不需要加锁,所以get方法就是一个普通的不加锁的方法。

  • set(E e):执行写操作时,首先进行lock加锁,然后复制原数组,创建一个长度+1的新数组,在新数组执行新增操作。完毕后,将新数组替换旧数组。由于数组时volatile的,所以替换之后,多线程之间是可见的。

五、BlockingQueue阻塞队列

BlockingQueue 不接受 null 元素。试图 add 、 put 或 offer ⼀个 null 元素 时,某些实现会抛出 NullPointerException 。 null 被⽤作指示 poll 操作失败的警戒值。

阻塞队列常用的方法

offer()如果队列满了无法插入,立即返回false;poll()如果队列是空的无法删除,立即返回false。

更关注put()take()操作失败,阻塞是怎样实现的。

1.ArrayBlockingQueue

构造函数,默认采用非公平锁,底层使用对象数组保存元素

添加图片注释,不超过 140 字(可选)

put时,如果队列满了,notFull.await();notEmpty.signal()

take时,如果队列空了,notEmpty.await();notFull.signal()

2.LinkedBlockingQueue

构造函数默认长度,2^31,底层使用链表维护元素,在构造函数中,创建一个空的节点,作为整个链表的头节点。

put时,count.get()为capacity,notFull.await();执行完入队操作,如果队列未满,唤醒其他put导致阻塞的线程;c==0时,表明队列已经有元素,signalNotEmpty()

take时,count.get()为0,notEnpty.await();执行完出队操作,队列中仍有节点,signalNotFull()

3.SynchronousQueue(复杂,后续调查)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值