ConcurrentHashMap的rehash过程
2015-08-07 15:13
429 查看
void rehash() { HashEntry<K,V>[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity >= MAXIMUM_CAPACITY) return; /* * Reclassify nodes in each list to new Map. Because we are * using power-of-two expansion, the elements from each bin * must either stay at same index, or move with a power of two * offset. We eliminate unnecessary node creation by catching * cases where old nodes can be reused because their next * fields won't change. Statistically, at the default * threshold, only about one-sixth of them need cloning when * a table doubles. The nodes they replace will be garbage * collectable as soon as they are no longer referenced by any * reader thread that may be in the midst of traversing table * right now. */ HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1); threshold = (int)(newTable.length * loadFactor); int sizeMask = newTable.length - 1; for (int i = 0; i < oldCapacity ; i++) { // We need to guarantee that any existing reads of old Map can // proceed. So we cannot yet null out each bin. HashEntry<K,V> e = oldTable[i]; if (e != null) { HashEntry<K,V> next = e.next; int idx = e.hash & sizeMask; // Single node on list if (next == null) newTable[idx] = e; else { // Reuse trailing consecutive sequence at same slot HashEntry<K,V> lastRun = e; //这里注释说的很明白,就是为了重用链表上的已有节点 int lastIdx = idx; for (HashEntry<K,V> last = next; //这个for循环时为了找到rehash之后新的bucket 的Index不再改变的链表位置 last != null; last = last.next) { int k = last.hash & sizeMask; if (k != lastIdx) { //找到可重用部分的链表头部 lastIdx = k; lastRun = last; } } newTable[lastIdx] = lastRun; // Clone all remaining nodes for (HashEntry<K,V> p = e; p != lastRun; p = p.next) { //在重新hash的过程中只需要rehash到可重用链表头部就好了 int k = p.hash & sizeMask; HashEntry<K,V> n = newTable[k]; newTable[k] = new HashEntry<K,V>(p.key, p.hash, //在rehash过程中所有的不可重用节点都是new出来的 n, p.value); //这一点保证不会对原链表结构进行更改 } } } } table = newTable; }
最近看了http://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/对ConcurrentHashMap的解读,自己也看了一下其中的源码,总是晕晕的,先简单总结一下。可以看到rehash过程的主要思路就是找到“重用点”,也就是图中的红色节点,途中虚线框中的节点构成了可重用的节点链表。
相关文章推荐
- baseadapter.getItemId的使用方法:实现listview筛选、动态删除
- Vijos1053Easy sssp题解
- Android 属性动画(Property Animation) 完全解析 (上)
- Could not lock surface java.lang.IllegalArgumentException
- BZOJ2612 : [Poi2003]Sums
- 协议森林08 不放弃 (TCP协议与流通信)
- Android:利用SharedPreferences实现自动登录
- Codeforces Round #Pi (Div. 2) ——B. Berland National Library
- 《深入理解C++对象模型》读书笔记(二)
- JAVA正则表达式语法大全
- 动态代理
- 动态创建表格
- falsh 遮住div 解决方案
- [ExtJS5学习笔记]第第二十四次 Extjs5形式上gridpanel或表单数据后台传输remoteFilter设定
- 解决啃爹的使用 xib Autolaout后8.0以下系统无法滑动scrollView
- 参数估计:最大似然、贝叶斯与最大后验
- tiff格式图片
- jQuery日常使用2
- ExecuteScalar、ExecuteReader不只是我想的这样的用处。
- jQuery常规选择器