![](https://img-blog.csdnimg.cn/20201014180756724.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
foundation
文章平均质量分 69
Dylanioucn
想写一首关于世界的诗,以编程的方式~
展开
-
不加锁交替执行线程的两种思路(递加取余判断、环形链表步进)(无锁,存在线程安全问题,在此仅作为一种思路分享)
不加锁交替执行线程的两种思路(递加取余判断、环形链表步进)原创 2022-04-02 17:37:27 · 1004 阅读 · 0 评论 -
13行代码实现两个线程交替打印1-100内的整数(不加锁、递加取余判断),欢迎来挑战~
13行代码实现两个线程交替打印1-100内的整数,核心代码如下: private static int step = 0; public static void task(int max,int remainder){ while(step<=max) { if(step%2==remainder) System.out.println(Thread.currentThread().getName() + step++);原创 2022-01-14 21:03:22 · 230 阅读 · 0 评论 -
让星星⭐月亮告诉你,强软弱虚引用类型对象在内存足够和内存不足的情况下,面对System.gc()时,被回收情况如何?
一、⭐⭐⭐工具????????????Eclipse+JDK1.8注:测试前需配置eclipse的JVM运行参数:-Xmx10m -Xms10m(如何配置eclipse的JVM运行参数),只分配10M的内存。因为会使用创建指定大小字节数组的方式,来触发内存临界值(10M),进而观察内存足够和不足两种场景下不同引用类型的具体表现。二、⭐⭐⭐概念????????????1 强引用类型强引用类型的对象无特定类型,硬气!宁折不弯,即便在内存不足报OutOfMemmoryError(OOM)的情况下,也不肯原创 2021-04-06 19:06:28 · 419 阅读 · 2 评论 -
使用完全注解的方式进行AOP功能实现(@Aspect+@Configuration+@EnableAspectJAutoProxy+@ComponentScan)
1、简单介绍如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换.2、注解说明@Configuration//用于定义配置类,可替换xml配置文件@EnableAspectJAutoProxy(proxyTargetClass=true) //开启AspectJ 自动代理模式,如果不填proxyTargetClass=true,默认为false(代表即便你配置了@EnableAsp原创 2021-04-05 13:04:32 · 1216 阅读 · 6 评论 -
让星星⭐月亮告诉你,当我们在说CPU一级缓存二级缓存三级缓存的时候,我们到底在说什么?
到底什么是cpu缓存(cache)?1、要弄清cpu cache,要先搞懂内存,内存的分类现在,计算机具有两种不同类型的内存:⭐一种类型是在RAM模块中使用的类型,它是DRAM或动态RAM,DRAM是一种使用电容器存储数据的存储器,这些电容器必须经常用电,不断地动态更新,以存储数据。⭐但是,计算机使用的另外一种类型的内存,不必经常刷新。这种存储器被称为SRAM或静态RAM,SRAM是cpu缓存中使用的。而且由于不必不断刷新SRAM,因此它比DRAM快很多,而且价格也很昂贵。 2、cpu缓存的作用到原创 2021-04-03 18:39:24 · 490 阅读 · 0 评论 -
(加深理解)类初始化及实例对象初始化顺序
1、类初始化过程①一个类要创建实例需要先加载并初始化该类 ✦main方法所在类需要先加载和初始化②一个子类要初始化需要先初始化父类③一个类初始化就是执行<cinit>()方法 ✦<cinit>()方法由静态类变量显示赋值代码和静态代码组成 ✦静态类变量显示赋值代码和静态代码从上到下顺序执行 ✦<cinit>()方法只执行一次 ✦静态代码块只有在被第一次调用的时候才执行,且只执行一次2、实例初始化过程①实例初始化就是执行&l...原创 2021-03-25 22:14:41 · 350 阅读 · 0 评论 -
让星星⭐月亮告诉你,(局部变量表、操作数栈)当我们在执行i=i++及i++时,底层到底在执行什么?
遇到一个比较有意思的题目,看上去很简单,实际运行起来却不是那么回事了。会发现i=i++和i++两者运行结果居然不一样!主要是没理解清楚java方法执行时,局部变量和操作数栈的分配运行机制,这就分享给大家分析过程:public class AutoIncrement { public static void main(String[] args) { int i = 0; i++;//相当于i=i+1; /* 步骤说明: 1、将局部变量i的值0 load到操作数栈 局部变量 i原创 2021-03-25 22:10:52 · 146 阅读 · 0 评论 -
让星星⭐月亮告诉你,设计模式入门
原创 2020-11-16 17:21:51 · 75 阅读 · 0 评论 -
让星星⭐月亮告诉你,计算机组成(CPU、内存、存储设备、输入设备、输出设备、通信设备)
什么是计算机?计算机是存储和处理数据的电子设备。包括硬件(可见的物理部分)和软件(不可见的指令)两部分。指令控制硬件完成特定的任务。了解计算机硬件知识,能更好地理解程序指令是如何对计算机及其组成部分产生作用的。计算机由中央处理器(CPU)、内存(主存)、存储设备(磁盘(CD、光盘、闪存))、输入设备(键盘、鼠标)、输出设备(显示器、打印机)、通信设备(调制解调器、网卡)组成。这些组件通过一个被称为总线的子系统连接在一起。总线相当于一条连接各组件的管道,数据和电信号通过总线在各组件之间穿梭往来。在个人原创 2020-08-04 23:27:26 · 3264 阅读 · 0 评论 -
让星星⭐月亮告诉你,Java二叉查找树的基本实现
二叉树可分为满二叉树、完全二叉树、平衡二叉树(二叉查找树)、最优二叉树(哈夫曼树),此篇代码实现的是二叉查找树(左右子树深度之差的绝对值不超过1待实现)。package unittest;import java.util.Arrays;class Person implements Comparable<Person>{ private String name; private int age; Person(String name,int age){ this.name =翻译 2020-07-29 14:27:07 · 121 阅读 · 0 评论 -
静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例
1.静态代理:基本描述:静态代理代理的是某一个接口的实例对象,以接口的形式对外展示。当然如果不需要以接口的形式对外展示,直接代理对象即可。缺点:只能代理某一种类型,要想代理其他类型,需要修改代码。package unittest.proxy;interface StaticInterface{ void method();}class Target implements StaticInterface{ @Override public void method() { System原创 2020-06-29 22:20:56 · 741 阅读 · 0 评论 -
让星星⭐月亮告诉你,HashMap中红黑树TreeNode的split方法源码解读
PS:由于文档是我在本地编写好之后再复制过来的,有些文本格式没能完整的体现,故提供下述图片,供大家阅览,以便有更好的阅读体验:HashMap中红黑树TreeNode的split方法源码解读分析HashMap$TreeNode(既是树又是链表)的split方法的源码,会发现主要分两部分操作:数据从旧数组转移到新数组上来時,旧数组上的数据会根据(e.hash & oldCap) 是否等于0,重新rehash计算其在新数组上的索引位置,分成2类:① 等于0时,则将该树链表头节点放到新数组时原创 2020-06-20 15:04:30 · 1296 阅读 · 2 评论 -
让星星⭐月亮告诉你,HashMap之往红黑树添加元素-putTreeVal方法源码解读
PS:由于文档是我在本地编写好之后再复制过来的,有些文本格式没能完整的体现,故提供下述图片,供大家阅览,以便有更好的阅读体验:HashMap之往红黑树添加元素-putTreeVal方法源码解读当要put的元素所在数组索引位置已存在元素,且是红黑树类型时,就会调用putTreeVal方法添加元素到红黑树上,具体操作步骤如下:从根节点开始,到左右子树,层层递进,遍历红黑树,找到用于存放元素的合适位置;将元素放入指定位置,并修改链表/红黑树相关节点的前prev后next父parent子(left/r原创 2020-06-18 00:45:51 · 761 阅读 · 0 评论 -
HashMap之链表转红黑树(树化 )-treefyBin方法源码解读(所有涉及到的方法均有详细解读,欢迎指正)
PS:由于文档是我在本地编写好之后再赋值过来的,有些文本格式没能完整的体现,故提供下述图片,供大家阅览,以便有更好的阅读体验:HashMap之链表转红黑树(树化 )-treefyBin方法方法概述:先将链表节点转为树节点,再将都是红黑树节点的链表转为红黑树分析HashMap的put方法的源码时发现,当HashMap中某个链表上存储的元素个数达到TREEIFY_THRESHOLD(树化阈值)=8个时,会调用treeifyBin方法尝试将该链表转换成红黑树。(PS:为什么说是尝试,而不是原创 2020-06-17 10:32:47 · 2608 阅读 · 6 评论 -
让星星⭐月亮告诉你,HashMap中保证红黑树根节点一定是对应链表头节点moveRootToFront()方法源码解读
红黑树根节点若不为其对应链表的头节点,则按照下述步骤的处理,将根节点向前移动到头节点:将根节点从所在链表中删除,即链表的删除操作:修改根节点的前后节点的指向即可,即将根节点的上一节点的下一节点设置为根节点的下一节点,将根节点的下一节点的上一节点设置为根节点的上一节点。将根节点所在链表的头节点位置的值设置为根节点;将现有头节点的上一个节点设置为根节点,将根节点的下一个节点设置为现有头节点,将根节点的上一个节点设置为null.具体源码如下:/**HashMap$TreeNode的moveRootT原创 2020-06-09 23:45:42 · 432 阅读 · 0 评论 -
HashMap扩容时的rehash方法中(e.hash & oldCap) == 0算法推导
HashMap在扩容时,需要先创建一个新数组,然后再将旧数组中的数据转移到新数组上来此时,旧数组上的数据就会根据(e.hash & oldCap) 是否等于0这个算法,被很巧妙地分为2类:① 等于0时,则将该头节点放到新数组时的索引位置等于其在旧数组时的索引位置,记未低位区链表lo开头-low;② 不等于0时,则将该头节点放到新数组时的索引位置等于其在旧数组时的索引位置再加上旧数组长度,记为高位区链表hi开头high.具体,详见下述的算法推导解析:算法:(e.hash & old原创 2020-06-08 15:50:53 · 10212 阅读 · 33 评论 -
从底层数据结构和CPU缓存两方面剖析LinkedList的查询效率为什么比ArrayList低
虽然前面有写到LinkedList与ArrayList的增删改查效率的全面比较,但回想一下还是有必要对这两者的查询效率做一个单独的比较,也能进一步加深理解。这次分底层数据结构和CPU缓存两方面展开它们分别对查询效率的阐述。一、底层数据结构对查询效率的影响1.ArrayList底层数据结构ArrayList底层数据结构是动态数组,创建数组时会给它分配一整段连续的物理内存空间,只要知道数组首地址和数组存储的元素类型,就可以根据指定索引值直接推导得出该索引位置对应的内存地址,进而就可以直接访问得到到该内存地原创 2020-06-05 14:05:06 · 592 阅读 · 0 评论 -
让星星⭐月亮告诉你,分享开始读源码的感受,望共勉
这段时间,一直在钻HashMap的源码,越读到后面,心里越觉得有什么想要说的,下面通过HashMap的扩容方法引出我想分享的一些思考和感受。HashMap的resize扩容方法,最迷人之处在于其巧妙的运用了核心算法:e.hash&oldCap,据此算法将旧数组中的数据很有效的转移到了新数组的对应索引位置上。好像越来越意识算法的至关重要,而且更厉害的是,可以将数学公式恰到好处地运用在亟需它的场景里。能设计出如此这般算法的又该是何等神仙人物~源码解读,从一开始的生拉硬拽,东张西望,到处网罗各种文章资原创 2020-06-04 21:37:59 · 229 阅读 · 0 评论 -
让星星⭐月亮告诉你,HashMap在put数据时是如何找到要存放的位置的?
初印象:初识HashMap时,知道HashMap是用来存放Key-Value这样的键值对的,也知道HashMap的底层数据结构是:数组+链表+红黑树,且数组长度为2的x次幂。疑问:那么往HashMap中添加键值对时,是什么决定了键值对的存放位置呢?即存放位置是如何计算出来的呢?相同的疑问可能还会以下面的问题描述方式提出来:其他描述方式:1.向HashMap中put数据时,数据是如何找到HashMap中Node<K,V>[] table数组的对应索引下标位置的?2.HashMap在put&原创 2020-06-03 23:26:33 · 2125 阅读 · 0 评论 -
让星星⭐月亮告诉你,HashMap的resize()即扩容方法源码解读(已重新完善,如有不足之处,欢迎指正~)
分析HashMap的resize()即扩容方法的源码,会发现主要分两部分操作:为创建新数组初始化新数组容量和新数组扩容阈值;创建新数组后,需将旧数组数据转移到新数组上来具体,详见下述的源码解析:/**HashMap的resize()方法*//** * Initializes or doubles table size. If null, allocates in * accord with initial capacity target held in field thr原创 2020-06-02 23:57:16 · 229 阅读 · 4 评论 -
让星星⭐月亮告诉你,对Java总体认知(摘抄自《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》)
Java概述:Java不仅仅是一门编程语言,它还是一个由一系列计算机软件和规范组成的技术体系,该技术体系提供了完整的软件开发和跨平台部署的支持环境,并广泛应用于嵌入式系统、移动终端、企业服务器、大型机等多种场合。时至今日,Java已经吸引超过600多万的软件开发者,这是全球最大的软件开发团队。而且使用Java的设备数量已经超过了45亿部。其中有8亿多台个人计算机、21亿部移动电话和其他手持设备,35亿个智能卡、以及大量机顶盒、导航系统和其他设备。Java优点:Java之所以能收到如此广泛的认可,不仅仅翻译 2020-06-01 22:32:36 · 146 阅读 · 0 评论 -
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
分析HashMap的put方法的源码后发现,HashMap的扩容方法在两个场景下会被调用:初始化HashMap的链表数组时,会被调用,用来初始化链表数组的初始容量为16,以及初始化链表数组的阈值为初始容量16*负载因子0.75=12;当put到HashMap存储的元素个数超过阈值时,会被调用,用来将链表数组的容量和阈值都扩大为原来的2倍。具体,详见下述的源码解析:/*HashMap的put方法,实际上调用的是putVal方法/public V put(K key, V value) {原创 2020-06-01 16:53:21 · 267 阅读 · 0 评论 -
让星星⭐月亮告诉你,原码、反码、补码以及为什么要用反码和补码
转载自:cumtchwWhen you learn a knowledge, you must reach the level that you can use it profiently, not just know it or be familiar with ithttps://www.cnblogs.com/cumtchw/p/4523332.html机器数一个数在计算机中的二进制表示形式,叫做这个数的机器数,机器数是带符号的,在计算机中用一个数的最高位存放符号,正数为0,负数为1,比如,转载 2020-05-21 21:35:15 · 672 阅读 · 0 评论 -
让星星⭐月亮告诉你,LinkedList和ArrayList底层数据结构及方法源码说明
一、LinkedList(同时实现了List接口和Deque implements Queue接口)1.LinkedList底层数据结构是一个双向链表(每个节点除了本身元素外,还包含了要指向的前一个节点Node prev和后一个节点Node next),双向链表还记录了头节点Node first和尾节点Node last.2.链表的数据结构在逻辑上是连续的,但是在物理空间上是不连续的(因此,索引下标和头元素存放的物理内存地址是不相关的,所以不能根据索引下标直接获取到元素,需要循环遍历);3.Linke原创 2020-05-21 20:57:55 · 928 阅读 · 0 评论 -
让星星⭐月亮告诉你,2的n次幂与二进制位全为1之间的联系,为啥只差一个1
现象:2^3 = 8 = (1+2+4) +1 =(20+21+2^2)+1 即23-1=(20+21+22)2^4 = 16 = (1+2+4+8) +1 =(20+21+22+23)+1 即24-1=(20+21+22+2^3)观察上述现象,可以发现2^n次幂等于2的0次幂到2的(n-1)次幂的所有值相加后再加1.而2的0次幂到2的(n-1)次幂是连续的,对应到二进制的位里面,就全是连续的1111*111啦,在HashMap中计算数组下标时,就利用到了这一特性:数组长度为2^n(通过HashMa原创 2020-05-21 11:21:44 · 989 阅读 · 0 评论 -
让星星⭐月亮告诉你,HashMap之tableSizeFor(int cap)方法原理详解(分2的n次幂和非2的n次幂两种情况讨论)
方法说明:HashMap的tableSizeFor(int cap)方法,可以返回一个大于或等于给定cap值的2的n次幂的数值. /** * Returns a power of two size for the given target capacity. */ static final int tableSizeFor(int cap) { int n = cap - 1; //第一点:这里减1,是为了保证本身已经是2的n次幂的情形下(2^3原创 2020-05-21 11:08:47 · 455 阅读 · 0 评论 -
让星星⭐月亮告诉你,红黑树实现自平衡的原理图解及与二叉查找树的比较
1.红黑树五大原则:(1)节点为红色或黑色(2)根节点为黑色(3)红色节点的子节点和父节点不能为红色(4)从根节点到所有叶子节点的路径中黑色节点个数相同(5)叶子节点为黑色2.在红黑树增删数据时,先增删,增删后若不满足五大原则,则再对其进行调整(左旋、右旋、颜色改变),调整的处理实际上是节点属性值(节点颜色、节点父子节点的左右子树)的改变。3.有五大原则做保证,红黑树能实现自平衡,保证从根节点到叶子节点的所有路径中的最长路径不超过最短路径的2倍.(举例:根节点到左子树叶子节点全是黑色,而右子树原创 2020-05-21 09:47:56 · 525 阅读 · 0 评论 -
让星星⭐月亮告诉你,HashMap底层数据结构及其增put删remove查get方法的代码实现原理
1.HashMap底层数据结构是数组+链表(jdk1.7头插法<扩容时链表逆序可能会导致环形链表的问题出现> jdk1.8尾插法)+红黑树(jdk1.8).2.HashMap中数组的容量默认为16,负载因子默认为0.75,当数组的0-15个下标里有160.75=12个被使用时,且HashMap中存储的元素总个数大于64时,则发生扩容操作,数组的容量扩大为原来的2n.3.负载因子代表数组中存储数据密度的大小:负载因子越大,数组单位容量内存储的数据越多,不同元素之间(key不同,但计算得到的数组原创 2020-05-21 09:20:03 · 345 阅读 · 0 评论 -
让星星⭐月亮告诉你,正数负数的二进制位运算(左移 右移 无符号右移)
正数和负数需先转换成相应的二进制,再进行移位运算.详细举例如下:1、左移(向左移动,低位补0,没有无符号左移,因为左移不影响符号位):(1)正数左移 2<<1(a)2为正数,其原码反码和补码均 00000000 00000000 00000000 00000010(b)00000000 00000000 00000000 00000010 <<1 = 00000000 00000000 00000000 00000100 = 4(2)负数左移 -2<<1(a原创 2020-05-20 15:51:25 · 2676 阅读 · 2 评论 -
让星星⭐月亮告诉你,二进制加减运算基础
1.二进制只有0和12.二进制加减计算时逢二进一,就像十进制加减时是逢十进一,加法运算时很容易理解,但是减法运算时可能会有点不好理解,下面举例说明:3.二进制加法: 0+0=0 0+1=1 1+1=104.二进制减法: 0-0=0 0-1=1 注意:此时,由于0<1,0减1时,会向前借一位,本身变成2,[情形1]若被借的前一位是0,则还会继续向前借位,[情形2]若被借的一位是1,则直接减一),具体情形如下: [情形1] [情形2]原创 2020-05-20 13:36:11 · 1049 阅读 · 0 评论 -
让星星⭐月亮告诉你,二进制加减运算进阶(原码/反码/补码/-1-1=(-1)+(-1)=-2)
计算机中数据以二进制方式0或1进行存储,计算时也采用二进制进行,二进制计算过程中涉及到以下概念原码:数据对应的二进制表示,首位代表符号位0-正数,1-负数;反码:正数的反码等于其原码;负数的反码是在其原码的基础上,符号位不变,其他位取反;补码:由于直接采用反码计算,符号位也会参与计算,导致最终结果不准确,所以引进了补码.正数的补码等于其反码同样等于其原码;负数的补码等于其反码+1.所以,在根据补码推算原码时,需要逆向计算,先补码末位-1,再取反.举例:-1-1=(-1)+(-1)=-2(1)-1的原创 2020-05-20 13:15:08 · 2437 阅读 · 0 评论