Skip to content

慧策(一面) 已完结 ​

日期

2024 年 9 月 6 日

自我介绍 ​

面试官您好,我是 wmh,是软件工程专业的 25 届应届生。

我的主要技术栈是 Spring Boot、MySQL、Redis。也会使用前端框架 Vue3,有一定的运维经验。

在校参与过学校项目组工作,有在校团队项目经验。参与过需求分析、数据库设计、开发、测试、部署等项目全流程。

在校期间完成了定时微服务、在线判题平台、个人导航站等项目,也与项目组成员合作开发过学校实验室预约系统、低代码平台组件库设计、学校申硕平台的二次开发等。

在校期间多次参与竞赛,曾获蓝桥杯省一和 CCPC 河北省赛的铜奖。

定时微服务 ​

定到早上 8 点发布,你这个时间是怎么判断?怎么触发的? ​

任务创建使用了 Web 模块和迁移模块。

  1. web 模块:提供 api 接口用来提交、激活定时任务。
  2. 迁移模块:主要负责定期生成定时任务的工作,定时器创建后不会立即生成所以任务,这个任务是无限的,所以使用迁移模块定期生成最近 1 小时的任务。

任务的调度和触发使用到了 3 个模块和 2 个线程池。

  1. 调度模块:通过定时程序,每分钟将当前时间的所有分片放入线程池进行触发,每个线程对应一个分片。
  2. 触发模块:每秒进行一次轮循,将需要被执行的任务放入线程池进行执行,每个线程对应一个需要被执行任务。
  3. 执行模块:执行模块拿到任务,通过回调接口通知调用方,并记录日志。

迁移模块的定时是如何触发的? ​

使用 Spring 自带的定时任务 @Scheduled,抢到 Redis 分布式锁的线程执行迁移逻辑。

为什么要把任务放到 zset 里?是有一个什么样的考量? ​

定时任务是有序的,通过时间顺序来触发任务,能够提高访问速度。

JUC ​

创建一个线程池有哪些参数? ​

核心线程数、最大线程数、存活时间、任务队列、拒绝策略

项目里定义线程池是哪种类型的任务队列? ​

使用了较大容量的有界阻塞队列,避免无界阻塞队列会出现内存泄漏问题。

核心线程数设了 20,最大线程数设了100。现在有一个新的任务被提交,它在里面那个流转的这个流程是什么? ​

  1. 任务提交到线程池
  2. 线程池检查当前活动线程数
    1. 小于 20:使用核心线程
    2. 大于 20:创建新线程,并执行
  3. 执行任务
  4. 执行完成后判断活动线程
    1. 小于 20:线程存活
    2. 大于 20:等待存活时间后且未被使用,会被销毁

了解过什么 Java 中的锁? ​

  1. synchronized:同步代码块
  2. ReentrantLock:可重入的互斥锁
  3. ReentrantReadWriteLock:读写锁,允许多个读线程同时访问,但写线程独占访问
  4. StampedLock:提供了乐观读锁,性能更高,但使用起来更复杂

synchronized 怎么保证会被锁上? ​

  1. 每个对象在内存中都存在一个与之关联的隐式监视器锁(Monitor)。
  2. 当一个线程进入 synchronized 方法或代码块时,它会尝试获取该对象的监视器锁。如果成功,则进入同步块执行代码;否则,线程将被阻塞,直到锁被释放。
  3. 线程在退出同步方法或代码块时会自动释放该监视器锁。

Redis ​

Redis 分布式锁执行的命令是什么 ​

setnx

Redis 的持久化方式是什么?区别是什么? ​

RDB 是保存快照,AOF 是追加日志。

默认配置下,一分钟修改 10 个值,会被存到 RDB 吗? ​

不会,默认配置下一分钟至少 10000 次修改才会执行 RDB 备份。

save 900 1
save 300 10
save 60 10000

AOF 是逐条记录还是批量记录? ​

默认情况下 Redis 的 AOF 是逐条记录写操作。

ZSet 底层是什么数据结构? ​

跳表

跳表的结构和特点是什么? ​

跳表是链表的一种。相比普通链表,增加了多级索引,通过索引可以实现 O(logn)O(\log n) 的元素查找效率。

ZSet 取值的时间复杂度是多少? ​

O(logn)O(\log n)

平衡二叉树获取一个节点的时间复杂度是多少 ​

O(logn)O(\log n)

Java 集合框架 ​

HashMap 的数据结构是什么? ​

哈希表加链表或红黑树

HashMap 什么情况会扩容,扩容到多大? ​

存放数量大于容量 * 扩容因子(默认 0.75)时会触发扩容。

扩容到原来的 2 倍。

为什么扩容到 2 倍? ​

哈希表使用哈希值取模运算来确定元素存储的位置,当 HashMap 长度是 2 的幂次方时,取模操作能转化为位运算,提高操作效率。

HashMap 中链表过长会触发什么? ​

HashMap 容量达到 64 且链表长度大于 8 时会转换为红黑树

HashMap 中红黑树会变成链表吗? ​

当长度减少到 6 及以下时,红黑树会转换回链表。

ConcurrentHashMap 如何保证线程安全? ​

  1. 分段锁:早期版本整个哈希表被分成多个段,每个段有自己的锁。
  2. 节点锁:新版本每个桶有自己的锁。
    1. 对于链表,会在节点级别使用 synchronized 锁定
    2. 对于红黑树,会使用树锁。
  3. CAS 操作:在插入新元素时使用 CAS 操作来保证原子性
  4. Synchronized 和 ReentrantLock:在 rehash 时会使用内部锁来保证复杂操作的原子性

Java 基础 ​

有一个接口的方法是被 final 修饰了,能在实现类里面还能去实现吗? ​

接口方法不能用 final 修饰

重载和重写的区别 ​

  1. 重载是一个方法名通过不同的参数、返回值,有着不同的实现
  2. 重写是子类重写并覆盖父类的方法,要求方法名和参数一致

重写时可以修改可见范围吗? ​

子类重写可以放宽可见性,不能收紧可见性。

String 底层的结构是什么? ​

String 底层使用 final 修饰的字符数组( char[])或字节数组(byte[])

StringBuilder 和 StringBuffer 的区别 ​

StringBuffer 线程安全,StringBuilder 线程不安全

StringBuffer 怎么保证线程安全? ​

StringBuffer 中的 insert() 和 append() 方法使用 synchronized 修饰。

JVM ​

字符串存放在 Java 内存结构的哪里? ​

字符串常量池在 jdk7 之前存放在方法区,jdk8 以后存放在堆中。为了方便垃圾回收。

JDK1.8中字符串常量池和运行时常量池逻辑上属于方法区,但是实际存放在堆内存中

JVM 内存结构都有什么? ​

堆、虚拟机栈、本地方法栈、方法区、程序计数器

堆区再细分的话还有哪些区域? ​

  1. 年轻代
  2. 老年代
  3. 永久代 / 元空间

新生代常见的垃圾回收算法 ​

复制清除算法:将存活的对象从一个内存区域复制到另一个内存区域,释放掉不再使用的内存。

年轻代被划分为三个区域:伊甸园 Eden 区、幸存区 From Survivor 区和幸存区 To Survivor 区。

Java 的类加载的机制是什么 ​

双亲委派机制

类加载器自上而下都是什么? ​

  1. 启动类加载器
  2. 扩展类加载器
  3. 应用程序类加载器

写了和 Spring 包名相同的类和方法,调用时会执行哪一个? ​

来自 gpt-4o

如果你的项目使用默认的类加载器配置,那么一般情况下,应用类加载器会优先加载引入的Spring包中的类,因为这些类一般都已经被系统预先加载。

你的自定义类将不会被加载。

项目的类使用什么加载器?Spring 的类呢? ​

都是应用类加载器

SSM 框架 ​

解释一下什么是 IOC 和 DI ​

IOC 是控制翻转,核心是程序要依赖于接口,而不是具体实现类。

DI 是依赖注入,在需要其他对象时通过 Spring 传入。

DI 是 IOC 的一种实现方式。

DI 的底层原理是什么? ​

根据关系使用反射动态创建对象,并注入

Spring 的动态代理的两种类型是什么?区别是什么? ​

JDK 动态代理和 CGLIB 动态代理

  • JDK 动态代理通过实现接口
  • CGLIB 动态代理通过继承原始类

反射中去创建 Class 对象, .class 和 Class.forName() 的区别 ​

Xxx.class 是静态获取并具有具体类型的 Class 对象

Class.forName("xxx") 是动态获取并具有通用类型的 Class 对象。

java
Class<Main> class1 = Main.class;
Class<?> class2 = Class.forName("Main");

你在什么功能上用使用过 AOP ? ​

记录日志、鉴权

Spring 是如何读取配置文件的? ​

Spring Boot 使用 @ConfigurationProperties 和相关的注解来读取配置类中的属性。当在配置文件中定义了属性,Spring Boot 会在启动过程中解析这些配置,并将它们绑定到相应的配置类中。

Spring Boot 会在启动时加载所有的自动配置类,这些类会根据你的配置文件中的内容来进行相应的设置。

多个 application-xxx 配置文件如何控制使用哪个 ​

  1. 在 application 中配置: spring.profiles.active=dev
  2. 运行时指定参数: --spring.profiles.active=dev

多个配置文件的读取顺序是什么? ​

  1. bootstrap.yaml:最先加载,用于引导配置。
  2. application.yaml:作为默认配置文件加载。
  3. application-dev.yaml:在指定环境激活时加载,并覆盖 application.yaml 中的相同属性。
  4. Nacos 配置中心:从 Nacos 中加载的配置,覆盖本地配置中的相同属性。

拦截器和过滤器的区别?顺序是什么? ​

先触发过滤器,再触发拦截器

  1. 过滤器是 Tomcat 提供的
  2. 拦截器是 Spring 的组件

MySQL ​

InnoDB 和 MyISAM 的区别 ​

  1. InnoDB 支持行级锁和事务,MyISAM 只有表锁,没有事务。
  2. InnoDB 将索引和数据存放在一起,B+ 树叶子结点存放数据;MyISAM 将索引和数据分开存储,B+ 树中存放数据地址。

索引都有哪些类型? ​

  1. 主键索引
  2. 唯一索引
  3. 普通索引
  4. 联合索引
  5. 前缀索引

索引的数据结构是什么? ​

B+ 树

B+ 树相比二叉树的优点是什么? ​

B+ 树是多叉树,树结构扁平;二叉树层级更高,需要频繁进行平衡。

聚簇索引和非聚簇索引的区别 ​

聚簇索引通常是主键索引,叶子节点存放数据。

非聚簇索引通常是非主键的索引,叶子结点存放主键,需要回表查询。

联合索引 A、B,只查 B 会使用索引吗? ​

不能,联合索引需要满足最左匹配原则

where 条件先写 B 后写 A 会走索引吗?为什么? ​

会使用索引。

数据库优化器会识别索引的使用,不会因 where 子句中条件的顺序不同而影响索引的利用。

count(1)、count(*)、count(字段) 的区别 ​

count(*) 会被优化器优化成 count(0),和 count(1) 性能相同,统计行数。

count(字段) 会统计字段非 NULL 的行数。

left join、right join、inner join 的区别 ​

  1. left join:左表所有数据以及其交集部分
  2. right join:右表所有数据以及其交集部分
  3. inner join:两表交集部分

Spring 如何使用事务? ​

使用 @Transactional 注解

❓Spring 事务什么时候会失效?事务传播行为是什么? ​

TBD...

事务的隔离级别有什么? ​

  1. 读已提交
  2. 读未提交
  3. 可重复读
  4. 串行化

MySQL 的事务问题都有哪些? ​

  1. 脏读:在一个事务读取了另一个事务未提交的数据
  2. 不可重复读:同一事务多次读取数据时得到不同的结果。
  3. 幻读:一个事务在第一次读取时的数据集与第二次读取时的数据集不一致
  4. 死锁:多个事务互相等待对方释放资源

Linux ​

看日志(文本文件)可以使用哪些命令 ​

cat、less、vim

cat 和 less 的区别 ​

cat 用于将文件内容输出到标准输出,适合短文本

less 可以逐页查看文件内容,适合长文本

less 打开文件是默认定位在第 0 行,还是最后一行? ​

默认情况下,它会定位在文件的 第0行(即文件的开头)

less 打开文件如何直接跳转到最后一行? ​

文件打开,按下 G 键(注意是大写的 G),你会直接跳转到文件的最后一行。

  • 按 g(小写)可以跳转到文件的第一行。
  • 使用方向键(上下箭头)或 j/k 键可以逐行移动。
  • 按 / 然后输入搜索词可以在文件中进行搜索。

如何能够持续查看新追加的内容,比如滚动的日志? ​

使用 tail -f xxx.log 命令,tail 会持续输出新追加的内容

如何修改文件权限 ​

chmod 命令

用户权限格式是什么? ​

-rw-r--r--@   1 wangminghao  staff    407665  8 10 14:35 wmh.pdf
  1. 第 1 位:- 文件、d 目录、l 链接文件
  2. 2-4 位:指文件拥有者的权限
  3. 5-7 位:指文件拥有者所在用户组的权限
  4. 8-10 位:其他用户的权限
权限缩写数字符号
读r4
写w2
执行x1
无权限-0

如何给文件加可执行权限? ​

sh
chmod +x script.sh

chmod 755 script.sh

数据结构 ​

快排的时间复杂度是什么 ​

O(logn)O(\log n),最差情况是 O(n2)O(n^2)

冒泡排序的时间复杂度是什么 ​

O(n2)O(n^2),最好情况是 O(n)O(n)

Released under the MIT License.