JDK1.8 中 ConcurrentHashMap源码分析(一)容器初始化

简介: 本文是博主学习JDK源码的记录,此为 ConcurrentHashMap源码分析(一),希望对大家有所帮助。

上一篇文章中说到如何使用IDEA搭建JDK1.8阅读学习环境,JDK1.8源码下载及获取、导入IDEA阅读、配置JDK源码。这篇文章将学习ConcurrentHashMap源码

🍀ConcurrentHashMap初始化

在jdk8的ConcurrentHashMap中一共有5个构造方法,这5个构造方法中都没有对内部的数组做初始化, 只是对一些变量的初始值做了处理。

jdk8的ConcurrentHashMap的数组初始化是在第一次添加元素时完成
在这里插入图片描述

    // 没有维护任何变量的操作,如果调用该方法,数组长度默认是16
    public ConcurrentHashMap() {
    }

    // 传递进来一个初始容量,ConcurrentHashMap会基于这个值计算一个比这个值大的2的幂次方数作为初始容量
    public ConcurrentHashMap(int initialCapacity) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException();
        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
                   MAXIMUM_CAPACITY :
                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
        this.sizeCtl = cap;
    }

    // 基于一个Map集合,构建一个ConcurrentHashMap
    // 初始容量为16
    public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
        this.sizeCtl = DEFAULT_CAPACITY;
        putAll(m);
    }

    // 调用四个参数的构造
    public ConcurrentHashMap(int initialCapacity, float loadFactor) {
        this(initialCapacity, loadFactor, 1);
    }

    // 计算一个大于或者等于给定的容量值,该值是2的幂次方数作为初始容量
    public ConcurrentHashMap(int initialCapacity,
                             float loadFactor, int concurrencyLevel) {
        if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
            throw new IllegalArgumentException();
        if (initialCapacity < concurrencyLevel)   // Use at least as many bins
            initialCapacity = concurrencyLevel;   // as estimated threads
        long size = (long)(1.0 + (long)initialCapacity / loadFactor);
        int cap = (size >= (long)MAXIMUM_CAPACITY) ?
            MAXIMUM_CAPACITY : tableSizeFor((int)size);
        this.sizeCtl = cap;
    }

☘️JDK1.8中使用new ConcurrentHashMap(16)初始化,初始容量是多少?

JDK1.7 中ConcurrentHashMap(16),则初始容量是16。 JDK1.8则为32

再回顾下ConcurrentHashMap(int initialCapacity)构造方法,

    public ConcurrentHashMap(int initialCapacity) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException();
        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
                   MAXIMUM_CAPACITY :
                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
        this.sizeCtl = cap;
    }

主要看这个tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1))方法,参数为16 + 8 + 1

    // 返回设置值2倍的最近的2的次幂,前后距离相等时,向取取(3*2 = 6,距4和8一样,取8)
    private static final int tableSizeFor(int c) {
        int n = c - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

最终得到的初始容量为32。

☘️sizeCtl解释理解

sizeCtl变量是ConcurrentHashMap中一个非常重要的变量,而且具有非常丰富的含义。

它的值不同,对应的含义也不一样,这里我们先对这个变量不同的值的含义做一下说明,后续源码分析过程中,进一步解释。

sizeCtl初始值 含义
0 数组未初始化, 且数组的初始容量为16
正数 如果数组未初始化,那么其记录的是数组的初始容量;如果数组已经初始化,那么其记录的是数组的扩容阈值(数组的初始容量*0.75)
-1 数组正在进行初始化
小于0,并且不是-1 数组正在扩容, -(1+n),表示此时有n个线程正在共同完成数组的扩容操作
目录
相关文章
|
XML Java 数据格式
Spring IoC容器初始化过程(xml形式)
Spring IoC容器初始化过程(xml形式)
285 0
|
存储 安全 Java
【JDK 源码分析】ConcurrentHashMap 底层结构
【1月更文挑战第27天】【JDK 源码分析】ConcurrentHashMap 底层结构
【JDK 源码分析】HashMap 操作方法
【1月更文挑战第27天】【JDK 源码分析】HashMap Put 元素 初始化
|
Java 大数据 Maven
jdk17出现错误无法初始化主类 和NoClassDefFoundError:Vector的解决方法
在JDK 17中使用孵化模块Vector时遇到的“无法初始化主类”和“NoClassDefFoundError: Vector”错误的解决方法,通过在Maven项目中配置编译插件、编写测试代码、配置Java运行时环境,并提供了运行项目的示例。
706 9
jdk17出现错误无法初始化主类 和NoClassDefFoundError:Vector的解决方法
|
Kubernetes 容器 Perl
【赵渝强老师】K8s中Pod中的初始化容器
Kubernetes的Pod包含业务容器、基础容器、初始化容器和临时容器。初始化容器在业务容器前运行,用于执行必要的初始化任务。本文介绍了初始化容器的作用、配置方法及优势,并提供了一个示例。
330 1
|
Java
Java基础之 JDK8 HashMap 源码分析(中间写出与JDK7的区别)
这篇文章详细分析了Java中HashMap的源码,包括JDK8与JDK7的区别、构造函数、put和get方法的实现,以及位运算法的应用,并讨论了JDK8中的优化,如链表转红黑树的阈值和扩容机制。
318 1
|
算法 安全 Java
深入JDK源码:揭开ConcurrentHashMap底层结构的神秘面纱
【8月更文挑战第24天】`ConcurrentHashMap`是Java并发编程中不可或缺的线程安全哈希表实现。它通过精巧的锁机制和无锁算法显著提升了并发性能。本文首先介绍了早期版本中使用的“段”结构,每个段是一个带有独立锁的小型哈希表,能够减少线程间竞争并支持动态扩容以应对高并发场景。随后探讨了JDK 8的重大改进:取消段的概念,采用更细粒度的锁控制,并引入`Node`等内部类以及CAS操作,有效解决了哈希冲突并实现了高性能的并发访问。这些设计使得`ConcurrentHashMap`成为构建高效多线程应用的强大工具。
267 2
|
SQL Shell 数据库
在TDengine容器中创建初始化数据库的Shell命令实例
以上就是在Docker容器环境中部署并初始化TDengine数据库的全过程,希望对你有所帮助。
589 0
|
Java Spring 容器
使用ContextLoaderListener初始化Spring容器
使用ContextLoaderListener初始化Spring容器
|
消息中间件 Kubernetes 数据库
在k8S中,初始化容器(init container)概念原理是什么?
在k8S中,初始化容器(init container)概念原理是什么?