博客记录-day151-面试+力扣

一、面试

1、类加载的过程

✅Java中类加载的过程是怎么样的?

类加载是 JVM 将类的字节码加载到内存并转换为可用 Class 对象的过程,分为五个阶段。​​加载​ ​阶段通过类加载器(如引导类加载器、扩展类加载器)读取字节码并生成 Class 对象;​​验证​ ​阶段确保字节码符合 JVM 规范,包括文件格式、语义检查等;​​准备​ ​阶段为静态变量分配内存并赋予默认值(如 int 初始化为 0);​​解析​ ​阶段将符号引用(如方法名)转换为直接引用(内存地址);​​初始化​ ​阶段执行类构造器 <clinit> 方法,完成静态变量赋值和静态代码块执行。整个过程确保类的正确性和安全性。

2、双亲委派机制

✅什么是双亲委派?如何破坏?

双亲委派机制是类加载的核心规则,其流程为:当收到类加载请求时,先委派给父类加载器处理,仅当父类无法完成(如找不到类)时,子类加载器才尝试自己加载。这一机制通过分层隔离(如引导类加载器优先加载核心类)避免了重复加载和核心类被篡改的风险。典型应用场景包括 Tomcat 为每个 Web 应用提供独立类加载器以防止类冲突,JDBC 驱动通过线程上下文类加载器打破双亲委派以加载不同数据库驱动,以及热部署框架动态替换类时绕过双亲委派。

3、打破双亲委派机制的场景

✅Tomcat的类加载机制是怎么样的?

双亲委派机制并非绝对,某些场景需要打破它以满足需求。例如,Tomcat 的 Web 应用类加载器优先加载 WEB-INF/classes 下的类,而非委派给父加载器,从而实现应用隔离;JDBC 驱动通过线程上下文类加载器(TCCL)加载具体数据库驱动类,避免因双亲委派导致只能加载一个驱动;热部署框架(如 OSGi)动态替换类时,需绕过父加载器直接由子加载器加载新版本类,实现无重启更新。

4、synchronize 和 ReentrantLock 的区别

✅synchronized和reentrantLock区别?

synchronized 是 JVM 内置锁,基于监视器(Monitor)实现,支持非公平锁且不可中断,仅提供单一条件变量(wait/notify)。其优势是使用简单,由 JVM 自动释放锁,但缺乏灵活性。ReentrantLock 是 JDK 提供的 API,基于 AQS 实现,支持公平/非公平锁、可中断锁(lockInterruptibly())、多条件变量(newCondition()),且需手动释放锁。性能上,优化后的 synchronizedReentrantLock 接近,但后者在高并发场景下可通过条件变量实现更精细的线程控制。

5、MVCC 的作用

✅如何理解MVCC?

MVCC(多版本并发控制)通过保存数据历史版本,实现非锁定读(快照读),提升并发性能。其核心是为每行数据维护隐藏字段(如事务 ID DB_TRX_ID 和回滚指针 DB_ROLL_PTR),记录修改事务和版本链。读操作基于一致性视图(ReadView)过滤不可见版本,避免加锁阻塞写操作,而写操作通过生成新版本实现无锁并发。MVCC 是 MySQL InnoDB 在可重复读隔离级别下解决幻读的关键机制。

6、可重复读如何通过 MVCC 实现

✅如何理解MVCC?

在可重复读隔离级别下,MVCC 通过事务开始时生成的一致性视图(ReadView)保证多次读取结果一致。ReadView 记录当前活跃事务 ID,查询时通过版本链和可见性规则判断数据版本:若数据版本的事务 ID 小于 ReadView 的最小活跃事务 ID,或等于当前事务 ID,则可见。例如,事务 A 在读取期间,事务 B 修改了数据但未提交,事务 A 基于版本链读取事务 A 自身修改前的版本,从而避免脏读和不可重复读。

7、Spring AOP 的实现原理

✅介绍一下Spring的AOP

Spring AOP 基于动态代理实现切面编程,支持 JDK 动态代理(基于接口)和 CGLIB(基于继承)。核心流程包括:定义切面(Aspect)和通知(Advice),通过 ProxyFactory 创建代理对象,在目标方法调用前后织入增强逻辑(如日志、事务)。JDK 代理通过 InvocationHandler 拦截接口方法,CGLIB 通过生成目标类的子类覆盖方法并插入切面代码。AOP 在运行时动态生成代理对象,对原对象行为进行增强,实现解耦和代码复用。

8、ThreadLocal 的作用及使用场景

✅ThreadLocal的应用场景有哪些?

ThreadLocal 为每个线程提供独立变量副本,避免共享数据竞争。其核心是通过 ThreadLocalMap 存储线程本地变量,每个线程访问自己的副本。典型场景包括:数据库连接、用户会话(如 SecurityContext)的线程隔离,分布式事务中存储 XID。需注意手动调用 remove() 清理数据,防止线程池中线程复用导致内存泄漏。例如,在 Web 应用中,通过 RequestContextHolder 存储请求上下文,确保每个请求线程独立访问请求参数。

9、分布式锁的实现方式

✅分布式锁有几种实现方式?

分布式锁用于多节点环境下协调资源访问,常见实现方式有三种:​​数据库​ ​通过唯一索引插入记录获取锁,删除记录释放锁,但存在单点故障和性能问题;​​Redis​ ​ 利用 SET key value NX EX 10 原子命令实现锁,结合 Lua 脚本保证原子性,需处理锁续期(如 Redisson 的 WatchDog 机制);​​ZooKeeper​​ 通过创建临时有序节点,监听前序节点删除事件实现锁,可靠性高但性能较低。选择时需权衡一致性、性能和复杂度。

10、设计模式的种类

✅Spring中用到了哪些设计模式

设计模式分为三类共 23 种(GoF):​​创建型​ ​关注对象创建机制,包括单例(保证唯一实例)、工厂方法(延迟子类决定实例化)、抽象工厂(创建产品族)、建造者(分步构造复杂对象)、原型(克隆对象);​​结构型​ ​关注类与对象组合,如适配器(接口转换)、装饰器(动态扩展功能)、代理(控制访问)、组合(树形结构);​​行为型​​关注对象间通信,如观察者(事件通知)、策略(算法替换)、模板方法(定义骨架)、责任链(请求分发)。

11、分布式事务的实现方式

✅常见的分布式事务有哪些?

分布式事务通过跨服务数据一致性方案解决,主要分为强一致性和最终一致性两类。​​强一致性​ ​方案包括:​​2PC​ ​(两阶段提交)通过协调者统一提交/回滚,但存在同步阻塞问题;​​TCC​ ​(Try-Confirm-Cancel)通过业务补偿实现,需编写 Try、Confirm、Cancel 接口。​​最终一致性​ ​方案包括:​​本地消息表​ ​(如 RocketMQ 事务消息)将业务操作与消息记录本地提交,异步消费消息;​​Saga​​ 模式将长事务拆分为多个本地事务,通过补偿操作回滚。选择时需根据业务容忍度权衡一致性与复杂度。

12、分库分表的区分方式

✅什么是分库?分表?分库分表?

分库分表是解决单库性能瓶颈的两种策略:​​垂直分库​ ​按业务拆分(如订单库、用户库),解决资源竞争和扩展性问题,但需处理跨库事务;​​水平分表​ ​按规则(哈希、范围、时间)拆分单表数据,解决单表数据量过大导致的查询效率低下。例如,用户表按 user_id 哈希分 10 张表,分散存储压力。两者常结合使用(如先垂直再水平),需注意数据分布均匀性和跨分片查询优化。

13、数据倾斜的治理方式

✅什么是数据倾斜,会带来哪些问题?如何解决?

数据倾斜指计算节点负载不均,需针对性优化。​​识别热点 Key​ ​可通过采样或监控工具定位(如 Spark UI);​​加盐打散​ ​对 Key 追加随机后缀(如 key_1key_2),分散计算后聚合结果;​​两阶段聚合​ ​先局部聚合(带盐值)再全局聚合(去盐值);​​调整数据分布​​通过随机前缀或哈希分片均衡负载。例如,大表关联时对倾斜 Key 单独处理,避免 Shuffle 阶段数据堆积。

14、MySQL 的治理过程

MySQL 治理涵盖架构、优化、监控与高可用。​​架构层​ ​通过主从复制、读写分离分担压力,分库分表解决单表瓶颈;​​优化层​ ​包括索引优化(覆盖索引、最左前缀匹配)、SQL 优化(避免全表扫描、减少临时表);​​监控层​ ​利用慢查询日志定位低效 SQL,Percona Monitoring 分析性能指标,pt-query-digest 解析执行计划;​​备份​ ​结合物理备份(xtrabackup)和逻辑备份(mysqldump);​​高可用​​通过 MHA 自动故障转移或 GTID 实现主从切换,保障服务连续性。

二、力扣

1、乘积最大子数组

152. 乘积最大子数组

java 复制代码
class Solution {
    public int maxProduct(int[] nums) {
        int n=nums.length;
        int[][] dp=new int[n][2];
        dp[0][0]=nums[0];
        dp[0][1]=nums[0];
        int res=nums[0];
        for(int i=1;i<n;i++){
            dp[i][0]=Math.min(dp[i-1][0]*nums[i],Math.min(dp[i-1][1]*nums[i],nums[i]));
            dp[i][1]=Math.max(dp[i-1][1]*nums[i],Math.max(dp[i-1][0]*nums[i],nums[i]));
            res=Math.max(res,dp[i][1]);
        }
        return res;
    }
}

2、二叉树最大宽度

662. 二叉树最大宽度

java 复制代码
class Solution {
    Map<Integer,Long> map;
    int res;
    public int widthOfBinaryTree(TreeNode root) {
        map=new HashMap<>();
        dfs(root,1,0);
        return res;
    }
    public void dfs(TreeNode root,int dep,long point){
        if(root==null) return;
        if(!map.containsKey(dep)){
            map.put(dep,point);
        }
        long left=map.get(dep);
        res=Math.max(res,(int)(point-left)+1);
        dfs(root.left,dep+1,point*2);
        dfs(root.right,dep+1,point*2+1);
    }
}

3、打家劫舍

198. 打家劫舍

java 复制代码
class Solution {
    public int rob(int[] nums) {
        int n=nums.length;
        int[][] dp=new int[n][2];
        dp[0][1]=nums[0];
        for(int i=1;i<n;i++){
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]);
            dp[i][1]=dp[i-1][0]+nums[i];
        }
        return Math.max(dp[n-1][0],dp[n-1][1]);
    }
}

4、根据身高重建队列

406. 根据身高重建队列

java 复制代码
class Solution {
    public int[][] reconstructQueue(int[][] people) {
        // 身高从大到小排(身高相同k小的站前面)
        Arrays.sort(people, (a, b) -> {
            if (a[0] == b[0]) return a[1] - b[1];
            return b[0] - a[0];
        });

        LinkedList<int[]> que = new LinkedList<>();

        for (int[] p : people) {
            que.add(p[1],p);
        }

        return que.toArray(new int[people.length][]);
    }
}
相关推荐
三道杠卷胡4 小时前
【AI News | 20250424】每日AI进展
人工智能·pytorch·python·语言模型·github
油泼辣子多加5 小时前
2025年04月24日Github流行趋势
github
uhakadotcom7 小时前
人工智能如何改变医疗行业:简单易懂的基础介绍与实用案例
算法·面试·github
uhakadotcom9 小时前
企业智能体网络(Agent Mesh)入门指南:基础知识与实用示例
后端·面试·github
我的golang之路果然有问题10 小时前
给git配置SSH(github,gitee)
经验分享·笔记·git·学习·gitee·ssh·github
勤劳打代码11 小时前
游刃有余 —— Isolate 轻量化实战
flutter·github·dart
AI蜗牛车11 小时前
【LLM+Code】Github Copilot Agent/VsCode Agent 模式Prompt&Tools详细解读
人工智能·语言模型·github·copilot·agent
运营猫小海豚11 小时前
DooTask功能与企业适配性分析
开源·github
油泼辣子多加11 小时前
2025年04月23日Github流行趋势
github