设为首页 加入收藏

TOP

基于JDK1.8的ConcurrentHashMap分析(一)
2018-03-02 06:57:04 】 浏览:478
Tags:基于 JDK1.8 ConcurrentHashMap分析

之前看过ConcurrentHashMap的分析,感觉也了解的七七八八了。但昨晚接到了面试,让我把所知道的ConcurrentHashMap全部说出来。


然后我结结巴巴,然后应该毫无意外的话就G了,今天下定决心好好分析一下,这个万能的并发包,ConcurrentHashMap


分一下几个方面分析ConcurrentHashMap:


(一)put方法


public V put(K key, V value) {
    return putVal(key, value, false);
}


调用了putVal方法,传入三个参数。第一个为key,第二个为val,第三个为onlyIfAbsent(意思为: 如果为true,当插入的key相同时,不替换val值,默认是为false,替换最新的val值)


putVal方法比较多,我们分两个部分讲:


//第一部分
final V putVal(K key, V value, boolean onlyIfAbsent) {
    //对传入的参数进行合法性判断
    if (key == null || value == null) throw new NullPointerException();
    //计算键所对应的 hash 值
    int hash = spread(key.hashCode());
    int binCount = 0;
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        //如果哈希表还未初始化,那么初始化它
        if (tab == null || (n = tab.length) == 0)
            tab = initTable();
        //根据键的 hash 值找到哈希数组相应的索引位置
        //如果为空,那么以CAS无锁式向该位置添加一个节点
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            if (casTabAt(tab, i, null,
                        new Node<K,V>(hash, key, value, null)))
                break;                 
        }


我们看到第四行,如果key和val都为null,直接抛出异常,所以不能传入key和val都不能为null。


第二个注意点是 散列这个函数


static final int spread(int h) {
    return (h ^ (h >>> 16)) & HASH_BITS;
}


我在HashMap里面有介绍,我就不详细说了,反正很重要。


第三个注意点就是初始化table这个函数initTable


private final Node<K,V>[] initTable() {
    Node<K,V>[] tab; int sc;
    //如果表为空才进行初始化操作
    while ((tab = table) == null || tab.length == 0) {
        //sizeCtl 小于零说明已经有线程正在进行初始化操作
        //当前线程应该放弃 CPU 的使用
        if ((sc = sizeCtl) < 0)
            Thread.yield(); // lost initialization race; just spin
        //否则说明还未有线程对表进行初始化,那么本线程就来做这个工作
        else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
            //保险起见,再次判断下表是否为空
            try {
                if ((tab = table) == null || tab.length == 0) {
                    //sc 大于零说明容量已经初始化了,否则使用默认容量
                    int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                    @SuppressWarnings("unchecked")
                    //根据容量构建数组
                    Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                    table = tab = nt;
                    //计算阈值,等效于 n*0.75
                    sc = n - (n >>> 2);
                }
         

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Uboot 引导内核时加载地址与入口.. 下一篇解决PyCharm无法显示matplotlib绘..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目