JDK1.8逐字逐句带你理解ConcurrentHashMap(3)
引言
这篇是介绍ConcurrentHashMap的第三篇,第一篇主要介绍了在jdk1.8中所用到的一些关键知识点,第二篇主要学习了ConcurrentHashMap的组织结构与线程安全的实现,同时介绍了几个极其重要的内部类。这一篇主要是我学习领悟到的几个核心方法,包括扩容,添加和查找。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290
transfer方法(扩容方法)
再这之前,我大致描述一下扩容的过程:首先有且只能由一个线程构建一个nextTable,这个nextTable主要是扩容后的数组(容量已经扩大),然后把原table复制到nextTable中,这个过程可以多线程共同操作。但是一定要清楚,这个复制并不是简单的把原table的数据直接移动到nextTable中,而是需要有一定的规律和算法操控的(不然怎么把树转化为链表呢)。
再这之前,先简单说下复制的过程:
数组中(桶中)总共分为3种存储情况:空,链表头,TreeBin头
①遍历原来的数组(原table),如果数组中某个值为空,则直接放置一个forwordingNode(上篇博文介绍过)。
②如果数组中某个值不为空,而是一个链表头结点,那么就对这个链表进行拆分为两个链表,存储到nextTable对应的两个位置。
③如果数组中某个值不为空,而是一个TreeBin头结点,那么这个地方就存储的是红黑树的结构,这样一来,处理就会变得相对比较复杂,就需要先判断需不需要把树转换为链表,做完一系列的处理,然后把对应的结果存储在nextTable的对应两个位置。
在上一篇博文中介绍过,多个线程进行扩容操作的时候,会判断原table的值,如果这个值是forwordingNode就表示这个节点被处理过了,就直接继续往下找。接下来,我们针对源码逐字逐句介绍:
/*** Moves and/or copies the nodes in each bin to new table. See* above for explanation.*/private final void transfer(Node[] tab, Node[] nextTab) {int n = tab.length, stride; //stride 主要和CPU相关//主要是判断CPU处理的量,如果小于16则直接赋值16if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE)stride = MIN_TRANSFER_STRIDE; // subdivide rangeif (nextTab == null) { // initiating只能有一个线程进行构造nextTable,如果别的线程进入发现不为空就不用构造nextTable了try {@SuppressWarnings("unchecked")Node[] nt = (Node[])new Node,?>[n << 1]; //把新的数组变为原来的两倍,这里的n<<1就是向左移动一位,也就是乘以二。nextTab = nt;} catch (Throwable ex) { // try to cope with OOMEsizeCtl = Integer.MAX_VALUE;return;}nextTable = nextTab;transferIndex = n; //原先扩容大小}int nextn = nextTab.length;//构造一个ForwardingNode用于多线程之间的共同扩容情况ForwardingNode fwd = new ForwardingNode(nextTab);boolean advance = true; //遍历的确认标志boolean finishing = false; // to ensure sweep before committing nextTab//遍历每个节点for (int i = 0, bound = 0;;) {Node f; int fh; //定义一个节点和一个节点状态判断标志fhwhile (advance) {int nextIndex, nextBound;if (--i >= bound || finishing)advance = false;else if ((nextIndex = transferIndex) <= 0) {i = -1;advance = false;}//下面就是一个CAS计算else if (U.compareAndSwapInt(this, TRANSFERINDEX, nextIndex,nextBound = (nextIndex > stride ?nextIndex - stride : 0))) {bound = nextBound;i = nextIndex - 1;advance = false;}}if (i < 0 || i >= n || i + n >= nextn) {int<
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
