Java高并发编程实战7,ConcurrentHashMap详解

一、ConcurrentHashMap详解

1、HashMap

在JDK1.8以前,HashMap是基于数组 + 链表来实现的,HashMap是一个数组,每个数组元素又是一张链表。

当向HashMap中增加元素时,会先根据此元素Key的hash值计算出该元素将要保存在数组中的下标。如果多个元素计算出的下标值相同,就会以链表的形式存储在数组的同一个元素中。
Java高并发编程实战7,ConcurrentHashMap详解_第1张图片

2、JDK1.7中的ConcurrentHashMap

JDK1.7中的ConcurrentHashMap间接地实现了Map,并将每一个元素称为分段锁segment,每个segment都是一个HashEntry数组,称为table,table的每个元素都是一个HashEntry的单向队列。
Java高并发编程实战7,ConcurrentHashMap详解_第2张图片
默认情况下,ConcurrentHashMap会生成16个segment。

ConcurrentHashMap结构的目的是更加细粒度的给元素加锁,**HashTable是给整个容器加锁,ConcurrentHashMap是给每个segment加锁,**当一个线程修改segment 0时,其他线程也可以修改其它segment,即 只要不同的线程同一时刻访问的是不同的segment,就不会发生写冲突,比HashMap性能更好。

3、JDK1.8中的ConcurrentHashMap

JDK1.8中的Map数据结构改为数组+链表/红黑树的形式,加锁粒度更加小,性能更好。

当链表中的元素超过8个时,HashMap就会将链表转换为红黑树。

ConcurrentHashMap也改为了数组+链表/红黑树的形式,废弃了segment,直接采用volatile HashEntry对象保存,即对每一条数据直接通过volatile避免冲突,此外,JDK1.8中还对ConcurrentHashMap使用了更多的synchronized和CAS算法来保证线程安全。

Java高并发编程实战7,ConcurrentHashMap详解_第3张图片

二、CopyOnWrite

CopyOnWrite的操作步骤:

  1. 遇到写操作时,先将当前容器复制一份,然后向新容器里添加元素;
  2. 原容器可以处理读请求;
  3. 增加完元素后,再讲引用指向新的容器,原容器等待被GC回收;

CopyOnWrite利用冗余实现了读写分离,这样一来,既没有加锁,又以读写分离的形式处理了并发的读和写请求。
原容器负责读操作,新容器负责写操作,写完之后,再将引用指向新容器,回收原容器;

  • 写少读多的业务,更适合使用CopyOnWrite容器;
  • 写多读少的情况,就不适合,因为容器的复制比较消耗性能;
    Java高并发编程实战7,ConcurrentHashMap详解_第4张图片

三、BlockingQueue

BlockingQueue是线程安全的Queue,看一下BlockingQueue有哪些方法:
Java高并发编程实战7,ConcurrentHashMap详解_第5张图片

1、常用方法如下

  1. add():向BlockingQueue中增加元素,如果BlockingQueue中有剩余空间,则返回true,否则抛出异常,通常与poll()配合使用;
  2. offer():向BlockingQueue中增加元素,如果BlockingQueue中有剩余空间,则返回true,否则返回false,通常与poll()配合使用;
  3. put():向BlockingQueue中增加元素,如果BlockingQueue中有剩余空间,则直接入队,否则当前线程会一直等待,直到BlockingQueue中有剩余空间,通常与take()配合使用;
  4. poll():取出BlockingQueue队首元素,如果队列为空,则会持续等待一定的时间,如果等待之后队列仍然为空,则返回NULL;
  5. take():取出BlockingQueue队首元素,如果队列为空,则当前线程一直等待;
  6. contains():判断队列中是否包含某元素
  7. drainTo(Collection c):将队列中的元素全部转移到集合c中;
  8. drainTo(Collection c, int maxElements):将队列中的前maxElements个元素,转移到集合c中;
  9. remove():移除队列中的某元素

2、BlockingQueue的实现类

  1. ArrayBlockingQueue:由数组构成的有界阻塞队列,队列的大小由构造方法的参数指定,主要应用于生产速度和消费速度基本匹配的场景;
  2. LinkedBlockingQueue:由链表结构组成的有界阻塞队列,队列的大小由构造方法的参数指定,线程池大部分都是直接使用LinkedBlockingQueue;
  3. PriorityBlockingQueue:支持优先级排序的无界阻塞队列,排序规则可以通过构造方法中的Comparator对象指定,主要应用于电商抢购、会员的优先级、银行办理业务、VIP优先插队等场景;
  4. DelayQueue:支持延迟存取的无界队列,队列中的某个元素必须在一段时间后才能被取出;

Java高并发编程实战系列文章

Java高并发编程实战1,那些年学过的锁

Java高并发编程实战2,原子性、可见性、有序性,傻傻分不清

Java高并发编程实战3,Java内存模型与Java对象结构

Java高并发编程实战4,synchronized与Lock底层原理

Java高并发编程实战5,异步注解@Async自定义线程池

Java高并发编程实战6,通过AQS源码分析lock()锁机制

哪吒精品系列文章

Java学习路线总结,搬砖工逆袭Java架构师

10万字208道Java经典面试题总结(附答案)

SQL性能优化的21个小技巧

Java基础教程系列

Spring Boot 进阶实战
在这里插入图片描述

你可能感兴趣的:(Java高并发编程,java,开发语言,数据结构)