了解JUC

JUC

#概述

JUC指的是JDK1.5中提供的一套并发包及其子包:java.util.concurrent,java.util.concurrent.lock,java.util.concurrent.atomic
JUC的主要内容:阻塞式队列、并发映射、锁、执行器服务、原子性操作

#BlockingQueue - 阻塞式队列

概述

满足队列的特点:FIFO(First In First Out)
BlockingQueue在使用的时候需要容量,且容量是固定的,不可扩容
阻塞:如果队列为空,则试图获取元素的线程会被阻塞;如果队列已满,则试图放入元素的线程会被阻塞
BlockingQueue中不允许元素为null
适应于生产消费模型
了解JUC_第1张图片# 常用的实现类

  1. ArrayBlockingQueue - 阻塞式顺序队列:
    底层必然基于数组来存储数据
    使用的时候需要指定容量
  2. LinkedBlockingQueue - 阻塞式链式队列:
    底层必然基于节点来存储数据
    在使用的时候可以指定容量也可以不指定。如果指定容量,则容量不可变;如果不指定容量,则容量默认为Integer.MAX_VALUE = 231-1不可变。因为实际开发中,一般不会在队列中存储21亿个元素,所以一般认为此时的容量是无限的
  3. PriorityBlockingQueue - 具有优先级的阻塞式队列:
    底层是基于数组来存储元素
    使用的时候可以指定容量也可以不指定。如果不指定则默认初始容量是11
    PriorityBlockingQueue会对放入的元素来进行排序,要求元素对应的类实现Comparable接口,覆盖compareTo方法指定比较规则
    PriorityBlockingQueue在迭代遍历的时候不保证排序
  4. SynchronousQueue - 同步队列 - 在使用的时候不需要指定容量,容量默认为1且只能为1

扩展:BlockingDeque - 阻塞式双端队列
特点:允许从两端放入元素也允许从两端获取元素
遵循阻塞特点,在使用的时候需要指定容量

#ConcurrentMap - 并发映射
概述
ConcurrentMap及其子类是JDK1.5提供的一套用于对应高并发的映射机制
ConcurrentMap在并发的时候还能比较好的保证线程安全

#ConcurrentHashMap - 并发哈希映射
ConcurrentHashMap底层是基于数组+链表来存储,数组的默认容量是16(表示有16个桶),默认加载因子是0.75,默认扩容是增加一倍的桶数
ConcurretHashMap最多允许存在230个桶
在ConcurrentHashMap中,允许指定容量。这个指定的容量经过计算一定是2n的形式
在JDK1.8中,为了提高效率引入了红黑树机制。当桶中的元素个数超过8个的时候,这个桶中的链表扭转成一棵红黑树;如果红黑树的节点个数不足7个的时候,将红黑树扭转回链表。扭转成红黑树的前提:桶的数量>=64,那么也就意味着如果桶数<64,那么桶中的元素个数无论是多少都不会变成红黑树
红黑树:
本质上是一棵自平衡二叉查找树
二叉查找树(BST):在二叉树的基础上加入了排序机制,使得左子树一定是小于根,右子树一定是大于根
特征:
所有节点非红即黑
根节点为黑
红节点的子节点一定是黑的
最底下的叶子节点是黑色的空节点
从根节点到叶子节点经过的路径中的黑色节点个数一致,即黑节点的高度是一致的
新添节点的颜色一定是红色的
红黑树在构建过程中,每次添加一个新的节点都需要考虑是否需要修正:涂色、左旋、右旋
红黑树的时间复杂度是O(logn)
ConcurrentHashMap是一个异步线程安全的映射:采用了分段/桶锁机制。在后续版本中,ConcurrentHashMap在分段锁基础上引入了读写锁机制:
读锁:允许多个线程同时读,不允许线程写
写锁:只允许一个线程写,不允许线程读
ConcurrentHashMap利用锁保证线程安全,但是在使用锁的时候,造成CPU的资源浪费(例如线程调度,线程上下文切换等)。在JDK1.8中,考虑到锁所带来的开销,引入了无锁算法CAS(Compare And Swap,比较和交换)。因为CAS涉及到线程的重新调度问题,所以需要结合具体的CPU内核架构来设计,因此Java中的CAS底层是依靠C语言实现的。目前市面上,服务器中流行的内核架构都是支持CAS的
了解JUC_第2张图片#ConcurrentNavigableMap - 并发导航映射

提供了用于截取子映射的方法
ConcurrentNavigableMap是一个接口,所以使用的是它的实现类ConcurrentSkipListMap - 并发跳跃表映射 - 底层是基于跳跃表实现的
跳跃表:
针对有序列表进行操作
适用于查询多而增删少的场景
典型的"以空间换时间"的产物
跳跃表允许进行多层提取,最上层跳跃表的元素个数不能少于2个
如果在跳跃表中新添了元素,那么新添的元素是否要提取到上层的跳跃表中遵循"抛硬币"原则
跳跃表的时间复杂度是O(logn)

你可能感兴趣的:(了解JUC)