[java并发] java高并发系列 - 第26天:学会使用JUC中常见的结合,常看看

原文链接:查看原文

感谢公众号“ 路人甲Java”的分享,如有冒犯,请联系删除,快去关注他吧
在这里插入图片描述

本文内容:

  1. 了解JUC常见集合,学会使用
  2. ConcurrentHashMap
  3. ConcurrentSkipListMap
  4. ConcurrentSkipListSet
  5. CopyOnWriteArraySet
  6. 介绍Queue接口
  7. ConcurrentLinkedQueue
  8. CopyOnWriteArrayList
  9. 介绍Deque接口
  10. ConcurrentLinkedDequeue

JUC集合框架图

[java并发] java高并发系列 - 第26天:学会使用JUC中常见的结合,常看看_第1张图片

图中可以看到,JUC的集合框架也是从Map、List、Set、Queue、Collection等超级接口中继承而来的。所以,大概可以知道JUC下的集合包含了一些基本操作,并变得线程安全。


Map

CocurrentHashMap

功能和HashMap基本一致,内部使用红黑树实现的。

特性:

  1. 迭代结果和存入顺序不一致
  2. key和value都不能为空
  3. 线程安全的

ConcurrentSkipListMap

内部使用跳表实现的,放入的元素会进行排序,排序算法支持2种方式来指定:

  1. 通过构造方法传入一个 Comparator
  2. 放入的元素实现 Comparable 接口

上面2种方式必选一个,如果2种都有,走规则1

特性:

  1. 迭代结果和存入顺序不一致
  2. 放入的元素会排序
  3. key和value都不能为空
  4. 线程安全的

List

CopyOnWriteArrayList

实现List的接口的,一般我们使用 ArrayListLinkedListVector,其中只有Vector是线程安全的,可以使用Collections静态类的synchronizedList 方法对 ArrayList、LinkedList 包装为线程安全的List,不过这些方式在保证线程安全的情况下性能都不高。

CopyOnWriteArrayList是线程安全的List,内部使用数组存储数据,集合中多线程并行操作一般存在4种情况,读读读写写写写读,这个只有在写写操作过程中会导致其他线程阻塞,其他3种情况均不会阻塞,所以读取的效率非常高。

可以看一下这个类的名称:CopyOnWrite,意思是在写入操作的时候,进行一次自我复制,换句话说,当这个List需要修改时,并不修改原有内容(这对于保证当前读线程的数据一致性非常重要),而是在原有存放数据的数组上产生一个副本,在副本上修改数据,修改完毕后,用副本替换原来的数组,这样也保证了写操作不会影响读。

特性:

  1. 迭代结果和存入顺序一致
  2. 元素不重复
  3. 元素可以为空
  4. 线程安全的
  5. 读读、读写、写读3种情况不会阻塞,写写会阻塞
  6. 无界的

Set

ConcurrentSkipListSet

有序的Set,内部基于ConcurrentSkipListMap实现的,放入的元素会进行排序,排序算法支持2种方式来指定:

  1. 通过构造方法传入一个 Comparator
  2. 放入的元素实现 Comparable 接口

上面两种方式需要实现一个,如果2种都有,走规则1

特性:

  1. 迭代结果和存入顺序不一致
  2. 放入的元素会排序
  3. 元素不重复
  4. 元素不能为空
  5. 线程安全的
  6. 无界的

CopyOnWriteArraySet

内部使用CopyOnWriteArrayList 实现的,将所有的操作都会转发给CopyOnWriteArrayList。

特性:

  1. 迭代结果和存入顺序不一致
  2. 元素不重复
  3. 元素可以为空
  4. 线程安全的
  5. 读读、读写、写读都不会阻塞;写写会阻塞
  6. 无界的

Queue

Queue接口中的方法,我们再回顾一下:

操作类型 抛出异常 返回特殊值
插入 add(e) offer(e)
移除 remove() poll()
检查 element() peek()

3种操作,每种操作有2个方法,不同点是队列为空或者满载时,调用方法抛出异常还是返回特殊值,大家按照表格中的多看几遍,加深记忆。

ConcurrentLinkedQueue

高效并发队列,内部使用链表实现。

特性:

  1. 线程安全的
  2. 迭代结果和存入顺序一致
  3. 元素可以重复
  4. 元素不能为空
  5. 线程安全的
  6. 无界队列

Dequeue

先介绍一下Dequeue接口,双向队列(Dequeue)是Queue 的一个子接口,双向队列是指该队列两端的元素既能入队(offer) 也能出队(poll),如果将Dequeue限制为只能从一端入队和出队,则可实现栈的数据结构。对于栈而言,有入栈(push) 和 出栈(pop),遵循先进后出原则。

一个线程 collection,支持在两端插入和移除元素,名称 dequeue 是 “double ended queue” (双端队列)的缩写,通常读为 “deck” 。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。

此接口定义在双端队列两端访问元素的方法。提供插入、移除、和检查元素的方法。每种方法都存在两种方式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。

下表总结了上述12中方法:

[java并发] java高并发系列 - 第26天:学会使用JUC中常见的结合,常看看_第2张图片

ConcurrentLinkedDequeue

实现了Dequeue接口,内部使用链表实现的高效的并发双端队列。

特性:

  1. 线程安全的
  2. 迭代结果和存入顺序一致
  3. 元素可以重复
  4. 元素不能为空
  5. 线程安全的
  6. 无界队列

BlockingQueue

关于阻塞队列,上一篇有详细介绍,请查看:第25天的文章

你可能感兴趣的:(Java,#,Java并发)