ConcurrentMap 并发映射

一、概述

1.是JDK1.5提供的用于应对高并发以及保证安全性的一类映射

二、ConcurrentHashMap - 并发哈希映射

1.底层结构依然是依靠数组+链表

2.默认初始容量是16,默认加载因子是0.75,默认扩容是增加1倍

3. 底层采用了分桶锁(分段锁)机制保证并发性,在后续的版本中,在分段锁的基础上引入了读写锁的机制:

   a.读锁:允许多个线程同时读,不允许线程写

   b.写锁:允许一个线程写,不允许线程读

4.在JDK1.8中,采用了无锁算法CAS(Compare and Swap - 比较和交换)

CAS的语义:我认为V的值是A,如果是,那么将V的值更新为B,否则修改并告诉V的值实际为多少

V 内存值

A 旧的预期值

B 新的预期值

 

5.在JDK1.8中,引入红黑树机制。当桶中的元素个数超过8个的时候,可能会扭转成一棵树,但实际上桶的容量大于64才转换;

如果桶中元素个数不足7个,则会扭转回链表 - 扭转成红黑树的最小容量为64

解决问题:桶数越多,扩容的几率就越低,桶数越多,每一个桶中的元素个数越多,使用红黑树

 

6.红黑树:解决瘸腿二叉树的问题

a.本质上是一颗自平衡二叉查找树 - Binary Search Tree - BST

   二叉树 - Binary Tree - B-树 

b.查询效率的时间复杂度:O(logn)

c.二叉查找树:i.基于二叉树,ii.左子树小于根,右子树都大于根 

       

d.特点:

  i.所有的节点颜色非红即黑(比如写代码时:true为黑色,false为红色,或者1为黑色,0为红色,可以自定义)

  ii.根节点一定是黑的

  iii.红节点的子节点一定是黑节点,黑节点的子节点可以是红节点也可以是黑节点

  iv.最底层的叶子节点一定是黑色的空节点(在红黑树中空节点使用 NIL 表示)

  v.从根节点到任意一个叶子节点经过的黑色节点的个数一定相同,即黑色节点高度一致

  vi.新添加的节点的颜色一定是红节点

 红黑树图例:

示例:现有一串数字;11,2,14,1,7,13,5,8,需要构建一颗红黑树,如果构建如下第一个图,存在什么问题?

问题如下:左边的高度为3,右边的高度为2

 

针对上述问题进行调整,最终如下:将右边黑色14变为红色14,黑色13变为红色13

 

如果这时需要添加 数字4 这个元素,按照正常的规则,放在红5下,

并且按照规则,新增为红,但是红色节点下又必须为黑色的那么需要进行红黑树的修正

 

d:修正 - 红黑树的修正过程是一个链式过程:

  只要涂色开始,就会按照 涂色-左旋-右旋 进行修正,左旋后必定会进行右旋,只有右旋可能会单独操作,因为右旋是最后一步

  i,涂色:当前节点为红,父节点为红,且叔父节点为红,那么需要将父节点以及叔父节点涂黑,然后将祖父节点涂红

  ii,当前节点为红,父节点为红,且叔父节点为黑,且当前节点为右子叶,那么需要以当前节点为轴,进行左旋操作

    左旋:

 

        

  iii:当前节点为红,父节点为红,且叔父节点为黑,并且当前节点为左子叶,那么需要以父节点为轴,进行右旋

   右旋:    

      

 修正过程:

  

三、ConcurrentNavigableMap  - 并发导航映射

1.这类映射汇总提供了截取子映射的方法

2.ConcurrentNavigableMap 本身是一个接口,更常使用其实现类:

   ConcurrentSkipListMap - 并发跳跃表映射 - 底层是基于跳跃表来存储的

3.跳跃表:

  a.使用前提:元素有序

  b.实际使用过程中,跳跃表往往不止一层,最上层的跳跃表的元素个数不少于2个

  c.跳跃表适用于查询多而增删少的场景

  d.跳跃表是典型的以空间换时间的产物

  e.当新添元素的时候,这个元素是否需要提取到上一层跳跃表中,遵循“抛硬币”原则

  f.跳跃表查询的时间复杂度:O(logn)   注意:时间/空间复杂度中的对数默认以2为底,以其他为底的可以转为以2为底的 

 

posted @ 2020-06-06 13:47  alen-fly  阅读(255)  评论(0编辑  收藏  举报