一,jvm基础调优工具
1.1 jps 查看java进程
作用:
JVM Process Status Tool,显示虚拟机进程。
用法:
jps [-qmlvV]
2026/9/27大约 11 分钟
作用:
JVM Process Status Tool,显示虚拟机进程。
用法:
jps [-qmlvV]
①,以锁粒度的维度划分:
MDL锁:基于表的元数据加锁,加锁后整张表不允许其他事务操作。InnoDB中为了支持多粒度的锁,为了兼容行锁、表锁而设计的。AUTO-INC锁:这个是为了提升自增ID的并发插入性能而设计的。Record锁:也就是行锁,一条记录和一行数据是同一个意思。Gap锁:InnoDB中解决幻读问题的一种锁机制。Next-Key锁:间隙锁的升级版,同时具备记录锁+间隙锁的功能。数据类型和对应的数据结构:
| 数据类型 | 底层结构 | 场景 | 格式 |
|---|---|---|---|
| String | SDS | 缓存、分布式锁、分布式id | key:value |
| List | 压缩列表,双向列表,快速列表 | 购物车、分布式锁 | key:value1,value1,value2....... |
| Hash | 压缩列表,Hash表 | 列表结构、队列结构、栈结构 | key:field1:value1,field2:value2.......... |
| Set | 整数集合,Hash表 | 抽奖、点赞、求交集。 | key:value1,value2,value3....... |
| SortedSet | 压缩列表,跳表 | 排行榜 | key:score1-value1,score2-value2............. |

1、用户发送请求至前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
这篇文章主要是介绍:如何将配置类转换为BeanDefinition的,核心就是:ConfigurationClassPostProcessor
@Configuration、@Import、@ComponentScan的解析是在BeanFactoryPostProcessor的实现类ConfigurationClassPostProcessor中完成的,解析结果会被注册为BeanDefinition
三级缓存存放的是什么:
getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) 参数bean是方法doCreateBean方法通过反射实例化的对象。演练一下循环依赖的执行流程:
| 时间点 | A 的状态 | B 的状态 | 关键动作 |
|---|---|---|---|
| 1. 实例化 A | A_raw 生成 | 未创建 | 调用 A 的构造方法。此时不生成代理。 |
| 2. A 放入三级缓存 | A_raw 存在 | 未创建 | 存入 Lambda:() -> getEarlyBeanReference(A)。此时仍不生成代理。 |
| 3. 填充 A 的属性 | A_raw 存在 | 未创建 | 发现依赖 B,暂停 A 的创建,转去创建 B。 |
| 4. 实例化 B | A_raw 存在 | B_raw 生成 | 调用 B 的构造方法。 |
| 5. B 放入三级缓存 | A_raw 存在 | B_raw 存在 | 存入 Lambda:() -> getEarlyBeanReference(B)。 |
| 6. 填充 B 的属性 | A_raw 存在 | B_raw 存在 | 发现依赖 A,调用 getBean(A)。 |
| 7. B 获取 A 的代理 | A_proxy 生成 | B_raw 存在 | 从三级缓存执行 Lambda,A 的代理在此刻生成,放入二级缓存。B_raw 拿到 A_proxy。 |
| 8. B 的属性填充完成 | A_proxy 存在 | B_raw 持有 A_proxy | B 的其他属性注入完成。 |
| 9. B 初始化 | A_proxy 存在 | B_raw 初始化 | 执行 B 的 @PostConstruct、afterPropertiesSet 等。 |
| 10. B 生成最终代理 | A_proxy 存在 | B_proxy 生成 | 经过 BeanPostProcessor,B 的代理在此刻生成,放入一级缓存。 |
| 11. 回到 A 的填充 | A_raw 获取 B_proxy | B_proxy 已存在 | A 的依赖 B 注入完成(拿到 B_proxy)。 |
| 12. A 初始化 | A_raw 初始化 | B_proxy 已存在 | 执行 A 的 @PostConstruct 等。 |
| 13. A 的代理替换 | A_proxy 替代 A_raw | B_proxy 已存在 | Spring 检查二级缓存有 A_proxy,用其替换 A_raw,放入一级缓存。 |
| 14. 最终容器 | A_proxy | B_proxy | 两个代理对象都存在于一级缓存。 |
| 11到13步的处理中“替换”这个概念你可能会有这样的疑问 11.A_raw 获取 B_proxy,二级缓存中的 A_proxy又没获取B_proxy,直接用二级缓存中的 A_proxy代替A_raw,二级缓存中的 A_proxy的属性B不是null的吗? | |||
| 错误的理解(你以为的): |
给你一个 非严格递增排列 的数组 nums ,请你 原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。元素的 相对顺序应该保持一致 。然后返回 nums 中唯一元素的个数。
public class DeleteSortArrRepeat {
public static void main(String[] args) {
int[] arr = new int[]{0,1,2,2,3,4,4,5};
System.out.println(arr.length);
System.out.println(deleteRepeat(arr));
}
public static int deleteRepeat(int[] arr){
if(arr.length < 2){
return arr.length;
}
int length = arr.length;
// 提示有序: 这就保证了重复的数值是挨在一起的, pre相当慢指针
int pre = arr[0];
for (int i = 1; i < arr.length;i++){
if(pre == arr[i]){
length--;
}
pre = arr[i];
}
return length;
}
}
给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例 1:
输入:nums = [1,2,3]
输出:6
示例 2:
输入:nums = [1,2,3,4]
输出:24
示例 3:
输入:nums = [-1,-2,-3]
输出:-6
Resilience4j是一个轻量级、高性能并易于使用容错框架,设计灵感来源于Netflix 的Hystrix框架,采用广受欢迎的函数式编程风格。
第一步:导入jar
spring boot环境:
<!-- springboot3.x 使用resilience4j-spring-boot3-->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>2.3.0</version>
</dependency>
单例模式是创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点以供外部代码使用.
public class HungrySingleton {
// 1,私有化构造方法,避免通过new创建
private HungrySingleton(){
}
// 2,私有静态属性
private static HungrySingleton hungrySingleton = new HungrySingleton();
// 3,向外暴露访问静态属性
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}