[课本划重点]分布式java应用基础和实践-第四章 分布式java应用与sun jdk类库(1)
2016-08-26 20:32
363 查看
无药可救的我本来打算直接上ConcurrentHashMap...结果发现自己都写不明白...所以结合一下HashMap一起写了
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">------------划重点------------</span>
1.1初始化一个HashMap的过程:
loadFactor(装载因子)=0.75,initialCapacity(初始容量)=16,
threshold = loadFactor * capacity(当数组中的使用大小>=threshold 时,entry 数组容量扩充为当前大小的两倍,扩充时对当前entry对象数组的中的元素全部rehash,并填充数组,并重新设置threshold值)。
创建Entry对象数组的大小为如下代码片段
HashMap初始化的是entry对象数组
2.1初始化一个ConcurrentHashMap的过程:
和HashMap一样有 initialCapacity和loadFactor属性,不过还多了一个concurrencyLevel;调用空构造函数的值分别为16,0.75,16
基于上述三个属性值计算的的size值:
在concurrencyLevel为16的情况下最终计算出的ssize = 16
然后将ssize传入Segment的newArray方法,创建大小为16的Segment对象数组,创建segment对象时,就是创建一个指定大小为
------------------------------
1.2对于key为null的情况,HashMap的做法为获取Entry数组的第一个Entry对象,并基于第一个entry对象的next属性遍历,如果找到key为null的entry对象,则将value更新;如果没有找到的话,取当前数组的第一个entry对象:e,创建一个新的entry对象e2,key为null ,然后e2 的next 是e
2.2concurrentHashMap不论是key ,还是value 为null 都会抛出NullPointerException
------------------------------
1.3HashMap的put:
先获取key对象本身的hashCode值,然后对此hashCode做hash操作,实现如下
2.3ConcurrentHashMap的put:
和hashMap同样的hash操作后得到的值获取对应数组的segment对象,方法如下:
return segments[(hash >>> segmentShift)&segmentMask]
找到segment对象后,进行lock操作,接着判断当前存储的对象个数加1后是否大于threshold,如果大于,当前HashEntry对象数组大小扩大两倍,并将之前存储的对象都全部rehash,接下来的操作和HashMap一样,所以此处省略n个字。
完成设值之后释放锁,整个put动作完成。
总结:ConcurrentHashMap基于concurrencyLevel划分出多个segment,从而避免每次put操作都得锁住整个数组。在默认情况下,最佳情况下可以允许16个线程并发无阻塞的操作集合对象。
---------------------------
其它的方法都差不多的。。。不想写了。。。下次再写吧
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">------------划重点------------</span>
1.1初始化一个HashMap的过程:
loadFactor(装载因子)=0.75,initialCapacity(初始容量)=16,
threshold = loadFactor * capacity(当数组中的使用大小>=threshold 时,entry 数组容量扩充为当前大小的两倍,扩充时对当前entry对象数组的中的元素全部rehash,并填充数组,并重新设置threshold值)。
创建Entry对象数组的大小为如下代码片段
int capacity = 1; while(capacity < initialCapacity) capacity <<= 1capacity 才是真正的Entry对象数组大小,默认情况下为16
HashMap初始化的是entry对象数组
2.1初始化一个ConcurrentHashMap的过程:
和HashMap一样有 initialCapacity和loadFactor属性,不过还多了一个concurrencyLevel;调用空构造函数的值分别为16,0.75,16
基于上述三个属性值计算的的size值:
int sshift = 0; int sszie = 1; while(ssize < concurrencyLevel){ ++sshift; ssize <<= 1 ;// ssize = ssize * 2 }
在concurrencyLevel为16的情况下最终计算出的ssize = 16
然后将ssize传入Segment的newArray方法,创建大小为16的Segment对象数组,创建segment对象时,就是创建一个指定大小为
------------------------------
1.2对于key为null的情况,HashMap的做法为获取Entry数组的第一个Entry对象,并基于第一个entry对象的next属性遍历,如果找到key为null的entry对象,则将value更新;如果没有找到的话,取当前数组的第一个entry对象:e,创建一个新的entry对象e2,key为null ,然后e2 的next 是e
2.2concurrentHashMap不论是key ,还是value 为null 都会抛出NullPointerException
------------------------------
1.3HashMap的put:
先获取key对象本身的hashCode值,然后对此hashCode做hash操作,实现如下
h ^= k.hashCode(); h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4);得到的值与(capacity -1)进行按位与操作,得到对应的数组位置,然后通过next进行遍历,寻找hash值一样的的entry对象,有则更新,无则添加
2.3ConcurrentHashMap的put:
和hashMap同样的hash操作后得到的值获取对应数组的segment对象,方法如下:
return segments[(hash >>> segmentShift)&segmentMask]
找到segment对象后,进行lock操作,接着判断当前存储的对象个数加1后是否大于threshold,如果大于,当前HashEntry对象数组大小扩大两倍,并将之前存储的对象都全部rehash,接下来的操作和HashMap一样,所以此处省略n个字。
完成设值之后释放锁,整个put动作完成。
总结:ConcurrentHashMap基于concurrencyLevel划分出多个segment,从而避免每次put操作都得锁住整个数组。在默认情况下,最佳情况下可以允许16个线程并发无阻塞的操作集合对象。
---------------------------
其它的方法都差不多的。。。不想写了。。。下次再写吧
相关文章推荐
- 《分布式java运用:基础与实践》笔记1
- 介绍事务与分布式事务原理与实践、事务在Java程序中的应用
- [零基础学JAVA]Java SE应用部分-34.Java常用API类库 推荐
- 《分布式java运用:基础与实践》笔记2
- java反射基础知识(四)反射应用实践
- java反射基础知识(五)反射应用实践
- Java并发:分布式应用限流 Redis + Lua 实践
- JAVA基础:漫谈Java程序设计中的接口应用
- 创建以Microsoft .NET Remoting为基础的分布式应用架构
- 设计高可用Java企业级应用的最佳实践
- Java 理论与实践: 应用 fork-join 框架
- JAVA基础应用: 处理Java中的日期问题
- JAVA基础应用: 如何实现希尔排序算法
- Java安全通信、数字证书及数字证书应用实践
- JAVA 应用简单破解---类库提前加载
- Java安全通信、数字证书及应用实践
- java基础应用之关键字综述
- 创建以Microsoft .NET Remoting为基础的分布式应用架构
- java基础教程-网络应用
- [转载]创建以Microsoft .NET Remoting为基础的分布式应用架构