自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(139)
  • 问答 (1)
  • 收藏
  • 关注

原创 HTTP基础概念和HTTP缓存技术

HTTP是超文本传输协议,主要分为三个部分:超文本、传输、协议。

2024-05-11 19:04:40 563

原创 TCP/IP网络模型

网络接口层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。

2024-04-24 15:50:01 927 1

原创 Java并发AQS源码解析

AQS的核心思想是如果被请求的共享资源空闲,那么将当前请求资源的线程设置为有效的工作线程,并且为共享资源设置为锁定状态。这个机制AQS是用CLH队列锁(CLH是一个虚拟的双向队列,只存在节点Node之间的关联关系)实现的,即将暂时获取不到锁的线程加入到队列当中。一个Node就表示一个线程,保存了线程引用,当前节点在队列中的状态,前驱节点,后继节点。以上两个方式就是将未获得锁的线程放入等待队列尾部的实现代码,放入队列尾部之后,我们应该让线程进入等待状态,等待其他线程唤醒自己,具体实现代码如下。

2024-03-30 20:15:50 1021

原创 JDK8中ArrayList扩容机制

这是基于JDK8的源码分析,在JDK6之前以及JDK11之后细节均有变动!!首先来看ArrayList的构造方法对于无参或是指定初始化大小为0的情况,他们真正分配容量是在执行add()方法。现在以创建的ArrayList为例(初始化大小为0与无参创建的ArrayList扩容逻辑略有不同),接下来去查看add方法的源码进一步分析扩容逻辑这里调用了ensureCapacityInternal方法,我们进一步查看该方法代码接下来去查看grow方法源码,查看具体扩容逻辑。

2024-03-26 20:13:15 320

原创 解析SpringBoot自动装配原理前置知识:解析条件注释的原理

Spring提供了向Bean中自动注入依赖的这个功能,这个过程就是自动装配。SpringBoot的自动装配原理基于大量的条件注解ConditionalOnXXX,因此要先来了解一下条件注解相关的源码。

2024-03-23 21:15:55 321

原创 Java基础之类型擦除

因为泛型其实只是在编译器中实现的而虚拟机并不认识泛型类项,所以要在虚拟机中将泛型类型进行擦除。也就是说,在编译阶段使用泛型,运行阶段取消泛型,即擦除。擦除是将泛型类型以其父类代替,如String 变成了Object等。其实在使用的时候还是进行带强制类型的转化,只不过这是比较安全的转换,因为在编译阶段已经确保了数据的一致性。

2024-03-10 17:18:39 407

原创 Spring之BeanFactory与FactoryBean的区别

BeanFactory是Spring中工厂的顶层接口,也是IOC容器的核心接口,BeanFactory中定义了管理Bean的通用方法,职责包括实例化、定位、配置应用程序中的对象以及建立这些对象的依赖。BeanFactory只是一个接口,并不是IOC容器的具体实现。BeanFactory部分源码。

2024-03-08 19:24:34 926

原创 JVM篇:垃圾回收器

会对伊甸园,幸存区以及老年代进行全面垃圾回收,在老年代垃圾回收时为了满足JVM中的最大GC暂停时间参数来决定具体回收哪些区域的老年代(优先选择回收过后释放的内存空间最大的区域),在这个阶段会STW。优点:让单位时间内,垃圾回收的时间尽可能短(比如一个小时内进行了2次垃圾回收,一次回收需要0.2秒,那么一共需要0.4秒,单位时间内垃圾回收时间在总运行的时间的占比叫吞吐量,占比越低,吞吐量越高)缺点:由于采用的是标记清除的算法,因此会产生内存碎片,当新的对象无法添加时,会进行串行清除,这会导致清理时间过长。

2024-01-29 01:11:28 688

原创 JVM篇:垃圾回收算法

如下图所示,当伊甸园不满足容纳新的对象时,会进行一次小的垃圾回收(Minor GC),会将伊甸园中存活的对象复制到幸存区To中并且记录对象存活次数(每执行一次垃圾回收,所有没被回收的对象生命值+1,当生命值超过一定值后(最大为15次),则会放入老年代区域),然后将伊甸园内存清空,交换From与To的内存区域。当所有的区域都不能够满足容纳新的对象时,先回进行一次Minor GC,当回收完依旧无法满足容纳新对象则会进行一次大的垃圾回收Full GC,此次回收会对所有的区域进行垃圾回收。优点:不会产生内存碎片。

2024-01-28 00:30:11 589

原创 JVM篇:垃圾回收

除了以上四种引用,还存在一种终结器引用,当GC回收一个重写了finalize()方法的对象时,JVM会给被回收对象创建一个终结器引用,同时将该引用放入引用队列,通过一个FinalizerHandler线程去处理引用队列当中的终结器引用,首先是判断被回收对象是否执行了finalize()方法,如果没有则执行,等到下一次GC时才会去释放该对象。所谓可达性分析就是,在垃圾回收之前,对堆中所有的对象进行扫描,看是否被根对象(一定不会被回收的对象)直接或间接引用,如果是则无法被回收,没有被引用则可回收。

2024-01-26 23:41:19 1215 1

原创 JVM篇:直接内存

直接内存并不是JVM的内存结构,直接内存是操作系统的内存,Java本身并不能对操作系统的内存进行操作,而是通过调用本地方法。直接内存常用于NIO作为缓冲区存在,分配成本较高但是读写性能好,并且不受JVM内存回收管理。

2024-01-05 21:05:19 1102

原创 JVM篇:字符串常量池

常量池中的字符串仅是符号,第一次用到时才会变为对象利用串池的机制,来避免重复创建字符串对象字符串变量拼接的原理是StringBuilder(1.8之后)字符串常量拼接的原理是编译期优化可以使用intern方法,主动将串池中还没有的字符串对象放入串池。

2024-01-05 20:58:46 861

原创 JVM篇:JVM内存结构

虽然堆存在垃圾回收机制,但是垃圾回收机制只能回收不再使用的对象,如果对象正在被使用是不会被回收的,由于堆内存默认大小为4G,当我们的程序在短时间内的执行可能不会暴露堆内存溢出的情况,这时我们可以设置堆内存小一些进行测试(命令为-Xmx[指定大小])。常量池是*.class文件中的,当该类被加载时,它的常量池信息就会被放入运行时常量池,并把里面的符号地址变为真实地址(简而言之就是在运行时会将常量池中的#1,#2转化为内存中的真实地址,而不是#1#2)对于变量是否是线程安全,主要是看该变量是共享的还是私有的。

2023-12-28 21:52:01 758

原创 JVM篇:JVM的简介

JVM全称为Java Virtual Machine,翻译过来就是java虚拟机,Java程序(Java二进制字节码)的运行环境Java最大的一个优点是,一次编写,到处运行。之所以能够实现这个功能就是依靠JVM,这是因为JVM屏蔽字节码与操作系统之间的差异,对外提供了一致的运行环境。JVM提供了自动内存管理,垃圾回收功能数组下标越界检查多态JVM只能识别字节码文件,JVM本身并不清楚自己运行的java代码是什么。

2023-12-28 20:47:07 678

原创 Spring中常见的BeanFactory后处理器

先给出没有添加任何BeanFactory后处理器的测试代码在配置类中我们编写了如下信息同时还有一个Bean1添加了@Component注解并且能够被扫描到,所以理论上来讲,我们可以观察到五个beanName,那么执行测试代码观察输出结果可以看到,这里只输出了一个beanName,我们可以推测出其他注解没有生效,那么接下来我们将常用的BeanFactory后处理器也注册到BeanFactory后,观察输出结果。

2023-12-26 21:19:24 482

原创 Spring中常见的Bean后处理器

可以看到成功获取到了bean1与bean2对象,然后通过反射的方法将值set到bean3的属性当中即可,需要注意的是,在创建DependencyDescriptor时,第二个参数为false的意思如果单例池中找不到对应的类型时不报错,如果为true,那么单例池中不存在对应类型的对象时会报错。添加图中的代码,红框中的第一行代码是修改beanFactory的自动装配的解析器,修改过后可以获取@Value中的属性,这个东西我们后续会解释。接下来我们查看另一种Bean后处理器,首先给出Bean4中的代码。

2023-12-26 18:16:37 536

原创 Spring5底层原理之BeanFactory与ApplicationContext

读取xml文件的实现方式还有一种FileSystemXmlApplicationContext,这种实现方式与ClassPathXmlApplicationContext的区别在于前者可以指定配置文件在磁盘中的路径或是src下的路径,其他与后者无异。是Spring的核心容器,ApplicationContext的主要的方法均是调用BeanFactory的方法。BeanFactory表面只能getBean(),实际上控制反转,基本的依赖注入、直至Bean的生命周期的各种功能,都由它的实现类体提供。

2023-12-24 21:47:14 1048

原创 Zookeeper的学习笔记

原生Java APIZkClientCurator相较于原生Java API,Curator使用较为简单,其次,高版本的Curator可以向下兼容zk,但zk无法向下兼容Curator。

2023-12-22 21:44:42 1646

原创 Dubbo的学习笔记

Dubbo建议使用Zookeeper作为服务注册中心Zookeeper安装有两个需要注意的地方,首先是需要修改conf目录下的zoo_sample.cfg文件名,因为Zookeeper的生效配置文件名叫zoo.cfg,其次,需要修改该文件中的数据存放路径,最好和zookeeper安装目录同一路径zookeeper的启动,去bin目录下执行如下命令查看zookeeper的状态创建一个简单MVC项目后续我们在该项目上添加Dubbo。

2023-12-21 21:10:40 943

原创 dubbo-admin连接虚拟机中的zookeeper报错zookeeper not connected

可以优先查看总结看能否解决大家的问题,如果不能解决不需要查看解决过程浪费时间了。因此,问题的关键在于修改url路径,所以我们可以通过修改源代码中的url属性又或是直接修改配置文件中的url路径以上两种解决方法都可以解决我的zookeeper not connected报错。

2023-12-21 19:29:05 870 1

原创 Java对象结构

其实在 JDK1.6 之前,Java 内置锁还是一个重量级锁,是一个效率比较低下的锁,在 JDK1.6 之 后,JVM 为了提高锁的获取与释放效率,对 synchronized 的实现进行了优化,引入了偏向锁、轻 量级锁的实现,从此以后 Java 内置锁的状态就有了四种(无锁、偏向锁、轻量级锁、重量级锁), 并且四种状态会随着竞争的情况逐渐升级,而且是不可逆的过程,即不可降级,也就是说只能进 行锁升级(从低级别到高级别)。对齐字节并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。

2023-12-18 20:49:00 1086

原创 getResource()方法的使用以及路径问题

首先getResource()方法可以通过getClass().getClassLoader().getResource()和getClass().getResource()两种方式调用,这两种方式调用的区别在于。getClass().getClassLoader().getResource():这个方法是通过类加载器来加载资源的。getClass().getResource():这个方法是通过当前类的 class 文件所在的位置作为相对路径来搜索资源的。返回的 URL 是相对路径,受调用类的包的影响。

2023-12-14 18:05:31 917

原创 Spring基于XML文件配置AOP

而AOP是横向的对不同事物的抽象,属性与属性、方法与方法、对象与对象都可以组成一个切面,而用这种思维去设计编程的方式叫做面向切面编程。这种实现方式存在两个问题,一个是需要被增强的Bean对象需要硬编码指定,其次是增强方法也是被写死的,如果需要修改被增强的类或是修改增强方法都需要修改代码。:动态代理技术,在运行期间,对目标对象的方法进行增强,代理对象同名方法内可以执行原有逻辑的同时嵌入执行其他增强逻辑或其他对象的方法。目标方法执行前后执行,目标方法异常时,环绕后方法不再执行。创建增强类,编写前方法与后方法。

2023-12-09 21:35:54 1187

原创 Spring基于xml半注解开发

对于非自定义的Bean我们需要使用工厂来进行加载,需要使用@Bean注解,如果需要参数,对于基本类型需要@Value注解,对于引用类型,只要Spring中存在,可以直接根据类型注入。

2023-12-08 21:35:30 1102

原创 Spring框架学习:Bean生命周期

目录SpringBean的生命周期Bean实例属性填充三级缓存常用的Aware接口Spring IoC容器实例化Bean总结Spring Bean的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段:在属性注入中,存在三种情况:如果循环依赖的话,半成品的bean会被存储在内存中,不归Spring管控,那么在注入时,就无法从容器中获取到对应的bea

2023-12-08 19:54:08 981

原创 对Spring源码的学习:Bean实例化流程

Spring容器在进行初始化时,会将xml配置的的信息封装成一个BeanDefinition对象,所有的BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为sinaletonObiects的Map集合中,当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。接下来编写Bean后处理器来测试Bean后处理器两个方法的执行时机。

2023-12-07 21:41:06 925

原创 对Spring源码的学习:基于XML文件配置的开发流程

延迟加载Bean实际上是先加载了工厂Bean类,当需要用到Bean时,会从单例池中获取FactoryBean后调用该对象中的getObject()方法获取到真正的的Bean对象,并将该Bean对象缓存在factoryBeanObjectCache中,当使用到该Bean对象时从该Map中获取。需要注意的是,需要property标签中的属性的name应该是setXxx()方法中的Xxx第一个子母小写之后的字符,ref标签指的是bean定义的id。指定哪个工厂Bean的哪个方法完成Bean的创建。

2023-12-07 21:24:17 1129

原创 Redis中HyperLogLog的使用

在学习HyperLogLog之前,我们需要先学习两个概念UV:全称Unique Visitor,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站,只记录1次。PV:全称Page View,也叫页面访问量或点击量,用户每访问网站的一个页面,记录1次PV,用户多次打开页面,则记录多次PV。往往用来衡量网站的流量。

2023-12-06 19:51:31 1115

原创 Redis滚动分页的使用

如何实现Feed流的分页功能是一个复杂的问题,如果采用MyBatis中的分页插件是不能满足分页功能的,因为Feed流是一个动态的,数据会不断更新,因此数据的角标会不停更新,当我们需要查询第5-10条的数据时,可能又保存了一个新的数据到数据库,从而导致我们分页查找的数据存在与上一次查询的数据重复的问题,具体问题流程图如下。可以看到,他是从第一个分数等于5的开始计算,获取之后的三个元素,因此,我们需要在开发中,对偏移量进行计算,方便我们下次进行查询时设置偏移量,大概的Java代码如下。关注推送也叫Feed流。

2023-12-06 18:56:44 1201

原创 Redis的三种消息队列实现方式

为什么要使用Redis的消息队列?成本低,对于RabbitMQ或是Kafka来说,已经是重量级的消息队列。List结构:一种有序的双向链表PubSub发布订阅:基于点对点的消息模型Stream:在Redis5.0之后提供的,比较完善的消息队列模型。

2023-12-05 19:46:34 1213

原创 根据源码梳理Redisson的可重入、锁重试以及看门狗机制原理

可重入:利用hash结构记录线程id和重入次数。可重试:利用信号量和PubSub功能实现等待、唤醒、获取锁失败的重试机制。超时续约:利用watchDog,每隔一段时间,重置超时时间。

2023-12-04 20:20:06 1843

原创 Redis中分布式锁的使用

满足分布式系统或集群模式下多进程可见并互斥的锁。

2023-12-03 21:17:36 972

原创 Redis缓存的使用

缓存就是数据交换的缓冲区,是存储数据的临时地方,一般读写性能较高。降低后端负载提高读写效率,降低响应时间数据一致性成本代码维护成本运维成本。

2023-12-02 21:48:11 1184

原创 通过查看ThreadLocal的源码进行简单理解

在多线程下,如果同时修改公共变量可能会存在线程安全问题,JDK虽然提供了同步锁与Lock等方法给公共访问资源加锁,但在高并发的场景下,如果多个线程争抢一把锁会出现大量的锁等待时间,让系统的响应时间变慢。对set方法中进行断点查看,当线程a第一次执行set时,先获取ThreadLocalMap对象是否为空,如果为空,那么执行createMap方法,将当前线程与需要存储的值作为参数传递。在get方法中,获取当前线程以及线程中的map对象,从对象中根据key获取存储的值并返回。

2023-12-02 18:24:53 589

原创 Redis的基本数据类型及常用命令

适合存储对象,因为可以对单个字段进行CURD,并且占用内存更少,如果采用String类型保存Java对象,需要进行序列化JSON形式的字符串,需要保存很多的{} ,: , "" 的符号,而Hash类型不需要保存这些多余的符号。Redis中的SortSet是一个可排序的Set集合,与Java中的TreeSet相似,但底层实现差别较大,TreeSet是基于红黑树实现,且需要自己编写排序逻辑,而ScoreSet是基于score属性对元素排序,底层实现是一个跳表加hash表。不存在的key会被忽略。

2023-12-01 19:52:43 1232

原创 MySQL进阶知识:InnoDB引擎

当我们在一个事务中,执行多个增删改的操作时,InnoDB引擎会先操作缓冲池中的数据,如果缓冲区没有对应的数据,会通过后台线程将磁盘中的数据加载出来,存放在缓冲区中,然后将缓冲池中的数据修改,修改后的数据页我们称为脏页。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘 I/O。缓冲池,是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度。

2023-11-30 21:31:31 1115

原创 MySQL进阶知识:SQL性能优化

首先,根据创建索引时指定的索引长度,截取条件中的的对应长度字符取索引中获取第一次出现该索引的id,然后区聚集索引中根据id获取到行信息,从行信息中获取对应字段信息与语句中的信息对比,如果相同,则返回该行信息。可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。比如说,name字段存在单列索引,也和age、sex存在联合索引,那么在只查询name字段时,可能会走联合索引。

2023-11-30 15:10:56 1069

原创 MySQL进阶知识:锁

MySQL中的锁,按照锁的粒度分,分为以下三类全局锁:锁定数据库中的所有表。表级锁:每次操作锁住整张表。行级锁:每次操作锁住对应的行数据。

2023-11-29 20:42:37 1102

原创 MySQL进阶知识:视图、存储过程、触发器

存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。存储过程思想上很简单,就是数据库SQL语言层面的代码封装与重用。封装,复用。可以接受参数,也可以返回数据。减少网络交互,效率提升。用户定义变量 是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用“@变量名”使用就可以。其作用域为当前连接。赋值语句# 推荐使用:= 因为可以与比较符号区分开。

2023-11-28 20:11:34 935

原创 SimpleDateFormat在多线程下的安全问题

SimpleDateFormat类是Java开发中的一个日期时间的转化类。它可以满足绝大多数的开发场景,但是在高并发下会出现并发问题。接下来查看下文中的案例。上面代码简单来说就是创建了一个SimpleDateFormat类对象,该对象被后续会被五个线程使用,去转化日期格式并打印。我们来查看输出结果。可以看到,只输出了一次时间转化,并且该输出格式还是错误的。接下来我们来查看为什么SimpleDateFormat类是线程不安全的。

2023-11-28 16:46:04 1159

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除