导航:首页 > 源码编译 > 底层源码原理

底层源码原理

发布时间:2024-08-28 03:37:57

㈠ JDK成长记7:3张图搞懂HashMap底层原理!

一句话讲, HashMap底层数据结构,JDK1.7数组+单向链表、JDK1.8数组+单向链表+红黑树。

在看过了ArrayList、LinkedList的底层源码后,相信你对阅读JDK源码已经轻车熟路了。除了List很多时候你使用最多的还有Map和Set。接下来我将用三张图和你一起来探索下HashMap的底层核心原理到底有哪些?

首先你应该知道HashMap的核心方法之一就是put。我们带着如下几个问题来看下图:

如上图所示,put方法调用了putVal方法,之后主要脉络是:

如何计算hash值?

计算hash值的算法就在第一步,对key值进行hashCode()后,对hashCode的值进行无符号右移16位和hashCode值进行了异或操作。为什么这么做呢?其实涉及了很多数学知识,简单的说就是尽可能让高16和低16位参与运算,可以减少hash值的冲突。

默认容量和扩容阈值是多少?

如上图所示,很明显第二步回调用resize方法,获取到默认容量为16,这个16在源码里是1<<4得到的,1左移4位得到的。之后由于默认扩容因子是0.75,所以两者相乘就是扩容大小阈值16*0.75=12。之后就分配了一个大小为16的Node[]数组,作为Key-Value对存放的数据结构。

最后一问题是,如何进行hash寻址的?

hash寻址其实就在数组中找一个位置的意思。用的算法其实也很简单,就是用数组大小和hash值进行n-1&hash运算,这个操作和对hash取模很类似,只不过这样效率更高而已。hash寻址后,就得到了一个位置,可以把key-value的Node元素放入到之前创建好的Node[]数组中了。

当你了解了上面的三个原理后,你还需要掌握如下几个问题:

还是老规矩,看如下图:

当hash值计算一致,比如当hash值都是1100时,Key-Value对的Node节点还有一个next指针,会以单链表的形式,将冲突的节点挂在数组同样位置。这就是数据结构中所提到解决hash 的冲突方法之一:单链法。当然还有探测法+rehash法有兴趣的人可以回顾《数据结构和算法》相关书籍。

但是当hash冲突严重的时候,单链法会造成原理链接过长,导致HashMap性能下降,因为链表需要逐个遍历性能很差。所以JDK1.8对hash冲突的算法进行了优化。当链表节点数达到8个的时候,会自动转换为红黑树,自平衡的一种二叉树,有很多特点,比如区分红和黑节点等,具体大家可以看小灰算法图解。红黑树的遍历效率是O(logn)肯定比单链表的O(n)要好很多。

总结一句话就是,hash冲突使用单链表法+红黑树来解决的。

上面的图,核心脉络是四步,源码具体的就不粘出来了。当put一个之后,map的size达到扩容阈值12,就会触发rehash。你可以看到如下具体思路:

情况1:如果数组位置只有一个值:使用新的容量进行rehash,即e.hash & (newCap - 1)

情况2:如果数组位置有链表,根据 e.hash & oldCap == 0进行判断,结果为0的使用原位置,否则使用index + oldCap位置,放入元素形成新链表,这里不会和情况1新的容量进行rehash与运算了,index + oldCap这样更省性能。

情况3:如果数组位置有红黑树,根据split方法,同样根据 e.hash & oldCap == 0进行树节点个数统计,如果个数小于6,将树的结果恢复为普通Node,否则使用index + oldCap,调整红黑树位置,这里不会和新的容量进行rehash与运算了,index + oldCap这样更省性能。

你有兴趣的话,可以分别画一下这三种情况的图。这里给大家一个图,假设都出发了以上三种情况结果如下所示:

上面源码核心脉络,3个if主要是校验了一堆,没做什么事情,之后赋值了扩容因子,不传递使用默认值0.75,扩容阈值threshold通过tableSizeFor(initialCapacity);进行计算。注意这里只是计算了扩容阈值,没有初始化数组。代码如下:

竟然不是大小*扩容因子?

n |= n >>> 1这句话,是在干什么?n |= n >>> 1等价于n = n | n >>>1; 而|表示位运算中的或,n>>>1表示无符号右移1位。遇到这种情况,之前你应该学到了,如果碰见复杂逻辑和算法方法就是画图或者举例子。这里你就可以举个例子:假设现在指定的容量大小是100,n=cap-1=99,那么计算过程应该如下:

n是int类型,java中一般是4个字节,32位。所以99的二进制:0000 0000 0000 0000 0000 0000 0110 0011。

最后n+1=128,方法返回,赋值给threshold=128。再次注意这里只是计算了扩容阈值,没有初始化数组。

为什么这么做呢?一句话,为了提高hash寻址和扩容计算的的效率。

因为无论扩容计算还是寻址计算,都是二进制的位运算,效率很快。另外之前你还记得取余(%)操作中如果除数是2的幂次方则等同于与其除数减一的与(&)操作。即 hash%size = hash & (size-1)。这个前提条件是除数是2的幂次方。

你可以再回顾下resize代码,看看指定了map容量,第一次put会发生什么。会将扩容阈值threshold,这样在第一次put的时候就会调用newCap = oldThr;使得创建一个容量为threshold的数组,之后从而会计算新的扩容阈值newThr为newCap*0.75=128*0.75=96。也就是说map到了96个元素就会进行扩容。

除了今天知识,技能的成长,给大家带来一个金句甜点,结束我今天的分享:坚持的三个秘诀之一目标化。

坚持的秘诀除了上一节提到的视觉化,第二个秘诀就是目标化。顾名思义,就是需要给自己定立一个目标。这里要提到的是你的目标不要定的太高了。就比如你想要增加肌肉,给自己定了一个目标,每天5组,每次10个俯卧撑,你看到自己胖的身形或者海报,很有刺激,结果开始前两天非常厉害,干劲十足,特别奥利给。但是第三天,你想到要50个俯卧撑,你就不想起床,就算起来,可能也会把自己撅死过去......其实你的目标不要一下子定的太大,要从微习惯开始,比如我媳妇从来没有做过俯卧撑,就让她每天从1个开始,不能多,我就怕她收不住,做多了。一开始其实从习惯开始,先变成习惯,再开始慢慢加量。量太大养不成习惯,量小才能养成习惯。很容易做到才能养成,你想想是不是这个道理?

所以,坚持的第二个秘诀就是定一个目标,可以通过小量目标,养成微习惯。比如每天你可以读五分钟书或者5分钟成长记,不要多,我想超过你也会睡着了的.....

最后,大家可以在阅读完源码后,在茶余饭后的时候问问同事或同学,你也可以分享下,讲给他听听。

㈡ 一文解密Kafka,Kafka源码设计与实现原理剖析,真正的通俗易懂

Apache Kafka (简称Kafka )最早是由Linkedln开源出来的分布式消息系统,现在是Apache旗下的一个子项目,并且已经成为开册、领域应用最广泛的消息系统之 Kafka社区也非常活跃,从 版本开始, Kafka 的标语已经从“一个高吞吐量、分布式的消息系统”改为“一个分布式的流平台”
关于Kafka,我打算从入门开始讲起,一直到它的底层实现逻辑个原理以及源码,建议大家花点耐心,从头开始看,相信会对你有所收获。

作为 个流式数据平台,最重要的是要具备下面 个特点

消息系统:
消息系统 也叫作消息队列)主要有两种消息模型:队列和发布订Kafka使用消费组( consumer group )统 上面两种消息模型 Kafka使用队列模型时,它可以将处理 作为平均分配给消费组中的消费者成员

下面我们会从 个角度分析Kafka 的几个基本概念,并尝试解决下面 个问题

消息由生产者发布到 fk 集群后,会被消费者消费 消息的消费模型有两种:推送模型( pu和拉取模型( pull 基于推送模型的消息系统,由消息代理记录消费者的消费状态 消息代理在将消息推送到消费者后 标记这条消息为已消费

但这种方式无法很好地保证消息的处理语义 比如,消息代理把消息发送出去后,当消费进程挂掉或者由于网络原因没有收到这条消息时,就有可能造成消息丢失(因为消息代理已经 这条消息标记为自己消费了,但实际上这条消息并没有被实际处理) 如果要保证消息的处理语义,消息代理发送完消息后,要设置状态为“已发送”,只有收到消费者的确认请求后才更新为“已消费”,这就需要在消息代理中记录所有消息的消费状态,这种做法也是不可取的

Kafka每个主题的多个分区日志分布式地存储在Kafka集群上,同时为了故障容错,每个分区都会以副本的方式复制到多个消息代理节点上 其中一个节点会作为主副本( Leader ),其 节点作为备份副本( Follower ,也叫作从副本)

主副本会负责所有的客户端读写操作,备份副本仅仅从主副本同步数据 当主副本 IH 现在故障时,备份副本中的 副本会被选择为新的主副本 因为每个分区的副本中只有主副本接受读写,所以每个服务端都会作为某些分区的主副本,以及另外一些分区的备份副本这样Kafka集群的所有服务端整体上对客户端是负载均衡的

消息系统通常由生产者“pro ucer 消费者( co sumer )和消息代理( broke 大部分组成,生产者会将消息写入消息代理,消费者会从消息代理中读取消息 对于消息代理而言,生产者和消费者都属于客户端:生产者和消费者会发送客户端请求给服务端,服务端的处理分别是存储消息和获取消息,最后服务端返回响应结果给客户端

新的生产者应用程序使用 af aP oce 对象代表 个生产者客户端进程 生产者要发送消息,并不是直接发送给 务端 ,而是先在客户端 消息放入队列 然后 一个 息发送线程从队列中消息,以 盐的方式发送消息给服务端 Kafka的记 集器( Reco dACCUl'lUlato )负责缓存生产者客户端产生的消息,发送线程( Sende )负责读取 集器的批 过网络发送给服务端为了保证客户端 络请求 快速 应, Kafka 用选择器( Selecto 络连接 读写 理,使网络连接( Netwo kCl i.ent )处理客户端 络请求

追加消息到记录收集器时按照分区进行分组,并放到batches集合中,每个分区的队列都保存了将发送到这个分区对应节点上的 记录,客户端的发送线程可 只使用 Sende 线程迭 batches的每个分区,获取分区对应的主剧本节点,取出分区对应的 列中的批记录就可以发送消息了

消息发送线程有两种消息发送方式 按照分区直接发送 按照分区的目标节点发迭 假设有两台服务器, 题有 个分区,那么每台服务器就有 个分区 ,消息发送线程迭代batches的每个分 接往分区的主副本节点发送消息,总共会有 个请求 所示,我 先按照分区的主副本节点进行分组, 属于同 个节点的所有分区放在一起,总共只有两个请求做法可以大大减少网络的开销

消息系统由生产者 存储系统和消费者组成 章分析了生产者发送消息给服务端的过程,本章分析消费者从服务端存储系统读取生产者写入消息的过程 首先我 来了解消费者的 些基础知识

作为分布式的消息系统, Kafka支持多个生产者和多个消费者,生产者可以将消息发布到集群中不同节点的不同分区上;“肖费者也可以消费集群中多个节点的多个分区上的消息 写消息时,多个生产者可以 到同 个分区 读消息时,如果多个消费者同时读取 个分区,为了保证将日志文件的不同数据分配给不同的消费者,需要采用加锁 同步等方式,在分区级别的日志文件上做些控制

相反,如果约定“同 个分区只可被 个消费者处理”,就不需要加锁同步了,从而可提升消费者的处理能力 而且这也并不违反消息的处理语义:原先需要多个消费者处理,现在交给一个消费者处理也是可以的 3- 给出了 种最简单的消息系统部署模式,生产者的数据源多种多样,它们都统写人Kafka集群 处理消息时有多个消费者分担任务 ,这些消费者的处理逻辑都相同, 每个消费者处理的分区都不会重复

因为分区要被重新分配,分区的所有者都会发生变 ,所以在还没有重新分配分区之前 所有消费者都要停止已有的拉取钱程 同时,分区分配给消费者都会在ZK中记录所有者信息,所以也要先删ZK上的节点数据 只有和分区相关的 所有者 拉取线程都释放了,才可以开始分配分区

如果说在重新分配分区前没有释放这些信息,再平衡后就可能造成同 个分区被多个消费者所有的情况 比如分区Pl 原先归消费者 所有,如果没有释放拉取钱程和ZK节点,再平衡后分区Pl 被分配给消费者 了,这样消费者 和消费者 就共享了分区Pl ,而这显然不符合 fka 中关于“一个分区只能被分配给 个消费者”的限制条件 执行再平衡操作的步骤如下

如果是协调者节点发生故障,服务端会有自己的故障容错机制,选出管理消费组所有消费者的新协调者节,点消费者客户端没有权利做这个工作,它能做的只是等待一段时间,查询服务端是否已经选出了新的协调节点如果消费者查到现在已经有管理协调者的协调节点,就会连接这个新协调节,哉由于这个协调节点是服务端新选出来的,所以每个消费者都应该重新连接协调节点

消费者重新加入消费组,在分配到分区的前后,都会对消费者的拉取工作产生影响 消费者发送“加入组请求”之前要停止拉取消息,在收到“加入组响应”中的分区之后要重新开始拉取消息时,为了能够让客户端应用程序感知消费者管理的分区发生变化,在加入组前后,客户端还可以设置自定义的“消费者再平衡监听器”,以便对分区的变化做出合适的处理


㈢ 什么是低代码开发

什么是低代码?

低代码开发平台(Low-Code Development Platform,LCDP)是低代码开发所需的环境。大多数低代码平台都是以云上提供的aPaaS(Application Platform as a Service,应用程序平台即服务)的形式,不仅用于开发,还用于应用程序的运行,实现了软件开发到应用的一贯性支持。

所谓低代码开发,是指尽量无需编写源代码,通过使用“图形用户界面/GUI”这一可视化操作,在极短的时间内实现系统开发的手法。目前也有通过在Web浏览器上搜索所需组件,整合粘贴来制作应用程序的工具。

采用低代码开发,无需SQL记述就可以制作数据库,简化开发工序。在保证一定扩展性的同时,可以有效缩短开发工时。

为什么选择低代码开发平台?

低代码开发平台最初被关注的是用于移动应用的开发。与基础系统开发相比,手机app开发对速度的要求更高,而且还必须支持多设备。在传统意义上,要在短时间内推出这样的移动应用程序是非常困难的,于是,低代码开发平台进入了开发人员的视野。

在现今社会,低代码开发平台受到关注的最大理由是数字化转型(DX)。所谓数字化转型,是指通过人工智能和物联网等信息技术,将一切事物通过数字数据连接起来,从而从根本上改变企业业务模式。

目前许多企业都在致力于数字化转型,以求在高速发展的时代中生存下来。企业的IT部门为了推进数字化转型,必须更密集的进行软件开发。但是,软件开发技术人员的数量是远远不够的,仅靠IT部门根本无法满足软件开发的需求。

低代码开发平台,可以被一般的业务人员、一线工作人员、管理人员等非专业的开发人员使用,无论是否有开发基础或经验,都可以经过简单的培训进行软件开发。

低代码开发的优势

缩短开发时间

低代码开发最大的优势是可以缩短开发时间,也就节约了开发成本。低代码开发平台提供了大量的通用组件,可以实现一些基础功能。必要时可以添加自己编写的代码,来满足用户的功能需求,提供质量稳定的应用程序。

无需担心安全性

低代码开发平台的供应商会提供相应的安全对策,用户无需担心程序的安全性以及开发过程中的安全风险。为了实现特殊功能,需要自己编写代码时,用户只需关注自己的编写部分的安全性即可。

降低开发门槛

在低代码开发中,无需编写复杂的源代码,就可以在专用的平台上编写程序。即使没有受过编程专业教育的人,也可以在平台上轻松地进行开发工作。在传统印象中,程序开发都是由专业的工程师来完成,使用低代码开发平台,程序开发的门槛大大降低了。

低代码开发平台的主要功能

通用性组件

低代码开发平台提供了大量通用的组件,这些可供使用的组件种类多样。

此外,用户也可以利用第三方开发的组件。这样的可再利用形式的组件,支撑着在低代码开发平台的视觉建模。

视觉建模

低代码开发平台以模型驱动型开发为基础,任何人都可以通过可视化建模,轻松实现程序开发。

通过拖放可以将所需的流程和组件整合,无需编程即可创建程序。同时,有编程技能的工程师也可以根据需要进行编码,从而定制组件。

支持各种架构

要开发与企业架构相对应的基础系统,就必须具备与各种系统协作的功能。在这一点上,低代码开发平台支持大多数的主流操作系统和数据库。

另外,通过丰富种类的API,可以和外部系统自由合作。因此,低代码开发平台具有可扩展性和开放架构,可支持大企业的基础系统开发。

基于代码的扩展

完全不使用代码的无代码工具,特点是使用预设好的功能来制作简单的应用程序。对于低代码开发平台,用户也可以通过编码自由扩展组件的功能。

低代码开发平台可以根据客户各自的需求,进行各种各样的定制,即使是复杂的大规模系统开发也能应对。

软件全生命周期整体支持

目前提供的低代码开发平台大部分采用的是云服务aPaaS的形式。

因此,低代码开发平台并非单纯的应用开发工具,从与数据库的自动连接、测试、正式启动、进一步运行管理、变更管理等开发工序到实际运用工序,搭载了支持整个软件生命周期的功能。

与无代码开发平台的区别

与低代码开发平台对应的是无代码开发平台(No-Code Development Platform, NCDP)。无代码顾名思义,就是不以编写代码为前提的开发方法。

低编码和无编码在某种程度上非常相似。前述的可视化建模、可再利用的通用性组件、生命周期管理等低代码开发平台的特征也适用于无代码开发平台。

无代码开发平台同样适用于专业的开发者和无基础开发者,提供了能够在更短的时间内轻松发布应用的环境。无需通过编码进行编程,通过PaaS平台提供,可以在不构建操作环境的情况下立即运行。

乍一看,无代码开发平台只是从低代码开发平台中去掉了编写代码的要素。但实际上它们是非常不同的。

首先,无代码开发平台不能通过编写代码来扩展或定制功能。因此,无代码开发平台目标是通过预先准备好的组件和API,实现功能范围内的相对简单的程序开发。不需要专业开发人员进行系统设计和数据库设计,经过简单的功能设计后立刻就可以使用。

典型的例子是使用Excel等电子表格的普通业务人员,将Excel和纸质工作系统化,自己创建应用程序,以简化日常工作。这些应用程序由其使用者来完成运营,随着业务的变化可以灵活的调整应用程序的功能。

无代码开发平台不能通过编写代码扩展功能,所以不适合功能较多的程序开发。此外,由于API的系统协作自由度较低,也不适合核心系统的开发。

低代码:朝着更好的未来行进

得益于一些厂商的努力,低代码行业正在构建起健康的生态。我们在讨论低代码的未来时,需要清楚一点的是,低代码并非万能,它有清晰的能力边界,而非一些声音所说的会“抢走程序员的饭碗”。低代码是企业数字化建设当中“最后一公里”,在保障企业数字化进程的价值赋能下,中国市场会有低代码的一方天地。

国内的简搭(jabdp)开发平台是一个低代码开发平台,复杂的业务功能,只需要会基本的sql语句和javascript语法,就能进行快速开发,满足其个性化的业务需求,设计出各种复杂的企业web应用。主要特点如下:

简搭(jabdp)低代码平台适合用于大部分的企业级web应用的开发,尤其适合企业信息管理系统(MIS)、企业资源计划系统(ERP)、客户关系管理系统(CRM),业务支撑系统(BSS)等。并且就一些经典的项目案例提取整合出各种类型的项目模板,共享给开发者参考,开发者可以在原有的项目基础上进行修改定制,以打造其个性化的企业信息化平台。

关于低代码开发平台,一个常见的误区是认为“低代码开发平台只适用于平民开发者(CitizenDeveloper)”。平民开发者是指那些非传统的、没有受过专业编程教育的开发者,他们主要用低代码平台来创造和定制应用。

当然,通过使用低代码开发平台,可以降低对多数项目人员的技术要求。在多个项目并行时,只需要一个有经验的程序员进行数据表、业务逻辑等的设计即可,其他项目人员无需编程能力,这样在人月数和人员要求两个方向都能有效控制项目的投入。

借助低代码开发平台,可以更高效地理解中小企业的信息化项目需求,控制项目开发的成本,同时适应中小企业信息化需求变化快和缺乏专业技术人员进行项目维护的特点,是开发中小企业信息化项目的最佳选择。

阅读全文

与底层源码原理相关的资料

热点内容
如何用电脑设置校时服务器 浏览:558
安卓什么软件可以换铃声 浏览:562
如何解决解压馆的劣势 浏览:320
plc编程模块化 浏览:245
单片机寄存器地址 浏览:396
七猫免费小说缓存加密 浏览:29
天津保税仓有溯源码 浏览:332
安卓9开发版什么时候推送 浏览:61
程序员可以天天加班吗 浏览:499
垃圾压缩车品牌 浏览:555
自制搜索引擎pdf 浏览:76
触漫安卓手机怎么登苹果的号 浏览:320
银行app怎么收信用卡的钱 浏览:288
java十进制转十六进制算法 浏览:920
pos刷卡需要app认证怎么弄 浏览:252
快速配IP命令 浏览:829
小程序后台源码导入 浏览:920
苹果手机app上的未读怎么取消 浏览:514
蜻蜓fm导出文件夹 浏览:514
我的世界怎么弄人家的服务器 浏览:361