1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
| // 创建新数组 private transient volatile Node<K,V>[] nextTable;
private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) { int n = tab.length, stride;
// 根据cpu个数找出扩容时的数组跨度大小 16,32,64 if ((stride = (NCPU > 1) ? (n >>> 3) / NCPU : n) < MIN_TRANSFER_STRIDE) stride = MIN_TRANSFER_STRIDE; // subdivide range
// 正式初始化 // 新创建nextTable,容量为原来的两倍 if (nextTab == null) { // initiating try { @SuppressWarnings("unchecked") Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1]; nextTab = nt; } catch (Throwable ex) { // try to cope with OOME sizeCtl = Integer.MAX_VALUE; return; } nextTable = nextTab;
//旧数组开始的转移位置,逆序迁移 transferIndex = n; }
// 创建扩容连接节点,将nextTable[]放入 int nextn = nextTab.length; ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
// 表示节点是否已经处理过 boolean advance = true;
// 扩容是否完成 boolean finishing = false; // to ensure sweep before committing nextTab
// 使用i表示当前处理的槽位,bound表示需要处理的槽位边界 for (int i = 0, bound = 0;;) { Node<K,V> f; int fh; while (advance) { int nextIndex, nextBound; if (--i >= bound || finishing) advance = false;
// 迁移到头了 else if ((nextIndex = transferIndex) <= 0) { i = -1; advance = false; } // i = 15,bound = 0 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 sc;
// 扩容完成,将nextTable赋值给table,清空临时表,重新设置sizeCtl if (finishing) { nextTable = null; table = nextTab; sizeCtl = (n << 1) - (n >>> 1); return; }
// CAS修改sizeCtl,sc - 1说明新增加扩容线程 if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) { if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT) return;
// 完成 finishing = advance = true; i = n; // recheck before commit } }
// 遍历的节点为空,放入Forwarding node else if ((f = tabAt(tab, i)) == null) advance = casTabAt(tab, i, null, fwd);
// 遍历到的节点为Forwarding node节点,说明被处理过了,直接跳过 else if ((fh = f.hash) == MOVED) advance = true; // already processed
else { // 锁住节点 synchronized (f) { if (tabAt(tab, i) == f) {
// 构造两个节点,在新数组中保存低位(0)和高位(1)的数组节点 Node<K,V> ln, hn;
// fh > 0,Node节点,获取 if (fh >= 0) {
// 获取原标志位,用于比较节点是否位于新数组 int runBit = fh & n; Node<K,V> lastRun = f;
// 遍历链表判断状态,记录下 runBit 和 lastRun for (Node<K,V> p = f.next; p != null; p = p.next) { int b = p.hash & n; if (b != runBit) { runBit = b; lastRun = p; } }
// 这里为两个链表设置头,一个正序,一个倒序 if (runBit == 0) { ln = lastRun; hn = null; } else { hn = lastRun; ln = null; }
// 遍历链表,根据标识位构造 ln链表和 hn链表 for (Node<K,V> p = f; p != lastRun; p = p.next) { int ph = p.hash; K pk = p.key; V pv = p.val; if ((ph & n) == 0) ln = new Node<K,V>(ph, pk, pv, ln); else hn = new Node<K,V>(ph, pk, pv, hn); }
// 在nextTable的 i 位置插入ln链表 setTabAt(nextTab, i, ln);
// 在nextTable的 i+n 位置插入hn链表 setTabAt(nextTab, i + n, hn);
// 设置forwarding节点,表示已经处理过了 setTabAt(tab, i, fwd);
// 标识advance 为true,i-- advance = true; }
// 对树节点进行处理 else if (f instanceof TreeBin) { TreeBin<K,V> t = (TreeBin<K,V>)f; TreeNode<K,V> lo = null, loTail = null; TreeNode<K,V> hi = null, hiTail = null; int lc = 0, hc = 0; for (Node<K,V> e = t.first; e != null; e = e.next) { int h = e.hash; TreeNode<K,V> p = new TreeNode<K,V> (h, e.key, e.val, null, null); if ((h & n) == 0) { if ((p.prev = loTail) == null) lo = p; else loTail.next = p; loTail = p; ++lc; } else { if ((p.prev = hiTail) == null) hi = p; else hiTail.next = p; hiTail = p; ++hc; } } ln = (lc <= UNTREEIFY_THRESHOLD) ? untreeify(lo) : (hc != 0) ? new TreeBin<K,V>(lo) : t; hn = (hc <= UNTREEIFY_THRESHOLD) ? untreeify(hi) : (lc != 0) ? new TreeBin<K,V>(hi) : t; setTabAt(nextTab, i, ln); setTabAt(nextTab, i + n, hn); setTabAt(tab, i, fwd); advance = true; } } } } } }
|