2019独角兽企业重金招聘Python工程师标准>>>

JUC包中集合类的框架,一般分为三部分:

  • List & Set
  • Map
  • Queue

一、List & Set

JUC集合包中的List和Set实现类包括

  • CopyOnWriteArrayList
  • CopyOnWriteArraySet

他们的框架如下图:

CopyOnWriteArrayList

  • CopyOnWriteArrayList实现了List接口,是基于数组实现的线程安全的List实现类
  • 内部原理是volatile数组+ReentrantLock互斥锁实现线程安全,每次更新操作时都会新建一个数组,把原来数组的数据copy到这个新数组,然后更新操作在新数组上面操作,最后在同步到volatile数组。 例如add源代码如下:
public boolean add(E e) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;Object[] newElements = Arrays.copyOf(elements, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}
  • 至于获取操作,直接就是返回volatile数组的对应数据,因为volatile数组保证了数据读是最新的数据

源代码如下:

public E get(int index) {return get(getArray(), index);
}
  • CopyOnWriteArrayList返回的iterator(),不是fail-fast机制,直接copy了一份当前的数据

源代码如下:

public Iterator<E> iterator() {return new COWIterator<E>(getArray(), 0);}static final class COWIterator<E> implements ListIterator<E> {/** Snapshot of the array */private final Object[] snapshot;/** Index of element to be returned by subsequent call to next.  */private int cursor;private COWIterator(Object[] elements, int initialCursor) {cursor = initialCursor;snapshot = elements;}public boolean hasNext() {return cursor < snapshot.length;}public boolean hasPrevious() {return cursor > 0;}@SuppressWarnings("unchecked")public E next() {if (! hasNext())throw new NoSuchElementException();return (E) snapshot[cursor++];}@SuppressWarnings("unchecked")public E previous() {if (! hasPrevious())throw new NoSuchElementException();return (E) snapshot[--cursor];}public int nextIndex() {return cursor;}public int previousIndex() {return cursor-1;}/*** Not supported. Always throws UnsupportedOperationException.* @throws UnsupportedOperationException always; {@code remove}*         is not supported by this iterator.*/public void remove() {throw new UnsupportedOperationException();}/*** Not supported. Always throws UnsupportedOperationException.* @throws UnsupportedOperationException always; {@code set}*         is not supported by this iterator.*/public void set(E e) {throw new UnsupportedOperationException();}/*** Not supported. Always throws UnsupportedOperationException.* @throws UnsupportedOperationException always; {@code add}*         is not supported by this iterator.*/public void add(E e) {throw new UnsupportedOperationException();}@Overridepublic void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);Object[] elements = snapshot;final int size = elements.length;for (int i = cursor; i < size; i++) {@SuppressWarnings("unchecked") E e = (E) elements[i];action.accept(e);}cursor = size;}}

而同时需要注意的是,CopyOnWriteArrayList返回的iterator(),是不支持add,set等更新操作的。

CopyOnWriteArraySet

  • CopyOnWriteArraySet实现了Set接口,基于数组实现的线程安全的Set类
  • CopyOnWriteArraySet包含了CopyOnWriteArrayList,其实大部分功能也是基于CopyOnWriteArrayList实现的,同CopyOnWriteArrayList一样,也是基于volatile和互斥锁实现线程安全。
  • CopyOnWriteArraySet使用了CopyOnWriteArrayList的addIfAbsent()和addAllAbsent()这两个添加元素的API,通过这些API来添加元素时,只有当元素不存在时才执行添加操作

源代码如下所示:

public boolean addIfAbsent(E e) {Object[] snapshot = getArray();return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :addIfAbsent(e, snapshot);
}private boolean addIfAbsent(E e, Object[] snapshot) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] current = getArray();int len = current.length;if (snapshot != current) {// Optimize for lost race to another addXXX operationint common = Math.min(snapshot.length, len);for (int i = 0; i < common; i++)if (current[i] != snapshot[i] && eq(e, current[i]))return false;if (indexOf(e, current, common, len) >= 0)return false;}Object[] newElements = Arrays.copyOf(current, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
}

二、Map

JUC集合包中Map的实现类包括:

  • ConcurrentHashMap
  • ConcurrentSkipListMap。

它们的框架如下图所示:

ConcurrentHashMap

  • ConcurrentHashMap是线程安全的哈希表,jdk8之前通过锁分段来保证线程安全的,但是在jdk8中,通过CAS思想重写了

以get源代码为例说明如何使用锁分段的,本代码基于jdk8

public V get(Object key) {Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;int h = spread(key.hashCode());if ((tab = table) != null && (n = tab.length) > 0 &&(e = tabAt(tab, (n - 1) & h)) != null) {if ((eh = e.hash) == h) {if ((ek = e.key) == key || (ek != null && key.equals(ek)))return e.val;}else if (eh < 0)return (p = e.find(h, key)) != null ? p.val : null;while ((e = e.next) != null) {if (e.hash == h &&((ek = e.key) == key || (ek != null && key.equals(ek))))return e.val;}}return null;
}

最关键的一句代码是

e = tabAt(tab, (n - 1) & h)

跟进去之后,发现是

/*** 获得在i位置上的Node节点*/
static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
}

是sun.misc.Unsafe的一些内部方法,Unsafe还有一些其他操作的方法也用到了ConcurrentHashMap中

/*** 利用CAS算法设置i位置上的Node节点。* 之所以能实现并发是因为他指定了原来这个节点的值是多少  * 在CAS算法中,会比较内存中的值与你指定的这个值是否相等,如果相等才接受你的修改,否则拒绝你的修改  * 因此当前线程中的值并不是最新的值,这种修改可能会覆盖掉其他线程的修改结果有点类似于SVN  */
static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,Node<K,V> c, Node<K,V> v) {return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
}/*** 利用volatile方法设置节点位置的值*/
static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
}

事实上,ConcurrentHashMap关键的一些操作交给了Unsafe这个JNI类控制,而Unsafe则是利用了CAS思想。

ConcurrentSkipListMap

  • ConcurrentSkipListMap是线程安全的有序的哈希表,适用于高并发的场景

三、Queue

JUC集合包中Queue的实现类包括

  • ArrayBlockingQueue 基于数组的阻塞安全队列
  • LinkedBlockingQueue 基于链表的单向FIFO阻塞安全队列
  • LinkedBlockingDeque 基于链表的双向FIFO、FILO阻塞安全队列
  • ConcurrentLinkedQueue 基于链表的单向FIFO非阻塞安全队列
  • ConcurrentLinkedDeque 基于链表的双向FIFO、FILO非阻塞安全队列

它们的框架如下图所示:

引用文章

  • JUC集合之框架
  • ConcurrentHashMap源码分析(JDK8版本)

转载于:https://my.oschina.net/haoran100/blog/725914

多线程(9)-JUC集合相关推荐

  1. java futher多线程_Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListMap类进行详细的介绍.内容包括: ConcurrentSkipListMap介绍 ConcurrentS ...

  2. Java多线程系列之“JUC集合“详解

    Java集合包 在"Java 集合系列01之 总体框架"中,介绍java集合的架构.主体内容包括Collection集合和Map类:而Collection集合又可以划分为List( ...

  3. Java多线程系列--“JUC原子类”01之 框架

    2019独角兽企业重金招聘Python工程师标准>>> Java多线程系列--"JUC原子类"01之 框架 根据修改的数据类型,可以将JUC包中的原子操作类可以分 ...

  4. Java多线程系列--“JUC原子类”03之 AtomicLongArray原子类

    概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...

  5. java并发编程(二十一)----(JUC集合)CopyOnWriteArraySet和ConcurrentSkipListSet介绍

    转载自  java并发编程(二十一)----(JUC集合)CopyOnWriteArraySet和ConcurrentSkipListSet介绍 这一节我们来接着介绍JUC集合:CopyOnWrite ...

  6. Java多线程系列--“JUC线程池”06之 Callable和Future

    转载自  Java多线程系列--"JUC线程池"06之 Callable和Future Callable 和 Future 简介 Callable 和 Future 是比较有趣的一 ...

  7. Java多线程系列--“JUC锁”05之 非公平锁

    转载自:http://www.cnblogs.com/skywang12345/p/3496651.html点击打开链接 概要 前面两章分析了"公平锁的获取和释放机制",这一章开始 ...

  8. Java多线程系列---“JUC锁”01之 框架

    本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下: 01. Java多线程系列--"JUC锁"01之 框架 02. Java多线程系列--"JUC锁 ...

  9. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对"公平锁"的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括: 基本概念 ReentrantLock数据结构 参考代码 获取公平锁(基于JDK1.7.0 ...

最新文章

  1. 在react hook里使用mobx(配置mobx依赖)
  2. C++成员变量初始化顺序问题
  3. sql server 链接服务器 改访问接口_跨服务器链接数据库?其实很简单!(上)
  4. StringBuffer类和String 类的 equals 和 ==
  5. UI5 Navigation execution entry point
  6. React开发(277):ant design time刚进入页面时间重置
  7. keil5建立工程步骤_5个步骤建立实践社区
  8. python解析pdf得到每个字符的坐标
  9. 让计算机教育因云而变,阿里云正式发布云原生人才培养合作计划
  10. ubuntu 虚拟机(转)
  11. 便携式CAN分析仪与毫米波雷达搭配使用
  12. EyouCms前台GetShell漏洞复现
  13. wps公式如何加序号_Microsoft Word 插入公式、公式编号及交叉引用完美指南
  14. gmail 设置 smtp_如何在Linux上使用Gmail或SMTP设置电子邮件警报
  15. 抖音如何接入在线客服系统?
  16. [附源码]计算机毕业设计springboot微信点餐系统
  17. 《REWORK》启示录一夜成名只是传说——创业一步步来
  18. 中秋节前能跟客户聊的!
  19. 3d编辑器的gizmo的缩放计算
  20. android 对短信的操作(伪造信息)

热门文章

  1. SQLCE数据库的几点研究
  2. request.getRequestURL()和request.getRequestURI()区别
  3. 在线手机号码VCF批量导入工具
  4. 智能交通|智慧产业园区管理系统集成搭建
  5. shell脚本监控cpu/内存使用率 转
  6. java正则学习笔记
  7. Magic Leap是快出产品的节奏,已开放内容开发者注册通道
  8. GPUImage API 文档之GPUImageFilter类
  9. 艾伟:WM有约(一):你好,CF
  10. Eclipse的两个hibernate plugin