Java 面试备战手册

Java 面试备战 · 完整版

覆盖并发、JVM、Spring、MySQL、Redis、分布式、微服务、Docker、LangChain4j 等 14 大专题。
点击题目展开答案,背熟后点右上角 ✓ 标记掌握。面试前一天只看未掌握项。

0题目总数
0已掌握
0%完成度
没有找到匹配的题目~
1

Java 并发、线程与锁

1.1进程和线程的区别?▶

进程是操作系统资源分配的基本单位,拥有独立地址空间、文件句柄;线程是 CPU 调度的基本单位,同一进程的线程共享堆和方法区,各自有独立的程序计数器、虚拟机栈。

  • 资源:进程独立,线程共享。
  • 切换开销:进程要切页表、刷 TLB,开销大;线程只保存寄存器和栈指针,开销小。
  • 通信:进程间需 IPC;线程直接读写共享变量。
  • 崩溃影响:进程隔离,一个崩溃不影响其他;线程崩溃可能拖垮整个进程。
1.2创建线程的四种方式?推荐哪种?▶
  1. 继承 Thread:无法再继承其他类,不推荐。
  2. 实现 Runnable:任务与线程解耦,推荐,但无返回值。
  3. 实现 Callable + FutureTask:有返回值、能抛异常。
  4. 使用线程池:生产环境首选,复用线程、控制并发、统一管理。
为什么用线程池:避免频繁创建销毁开销;限制并发防资源耗尽;提供队列、拒绝策略、监控。
1.3线程的六种状态?▶
  • NEW:新建,未调用 start()。
  • RUNNABLE:可运行,包含 OS 的就绪和运行中。
  • BLOCKED:等待 synchronized 锁。
  • WAITING:无限等待,wait/join/park。
  • TIMED_WAITING:超时等待,sleep(ms)/wait(ms)。
  • TERMINATED:终止。
注意:run() 就是普通方法调用,不会开新线程;start() 只能调一次,重复调用抛 IllegalThreadStateException。
1.4sleep、wait、yield、join 区别?▶
方法所属是否释放锁唤醒方式
sleepThread 静态否时间到自动醒
waitObject 实例是notify/notifyAll
yieldThread 静态否提示调度器让出 CPU
joinThread 实例是(内部 wait)目标线程结束
易错:sleep/wait 都会响应 interrupt 抛 InterruptedException,捕获后要恢复中断标志。
1.5如何优雅停止线程?▶

不要用 Thread.stop(),会导致锁突然释放、数据不一致。推荐中断标志 + 循环检查:

while (!Thread.currentThread().isInterrupted()) {
    // 业务逻辑
}
  • interrupt() 只是设置中断标志,不强制终止。
  • 阻塞方法(sleep/wait/join)会抛 InterruptedException 并清除标志。
  • 捕获后恢复标志:Thread.currentThread().interrupt()。
  • 可配合 volatile boolean 标志位。
1.6什么是线程安全?如何保证?▶

多线程并发访问共享可变状态,程序结果始终正确。线程不安全来自原子性、可见性、有序性三个问题。

五种保证方式
  • 不可变:final、String、LocalDate。
  • 互斥同步:synchronized、ReentrantLock。
  • 非阻塞同步:CAS、AtomicInteger。
  • 线程封闭:ThreadLocal、局部变量。
  • 无共享:每线程独立处理再合并。
项目结合:简历解析用局部变量 + 线程池,SimpleDateFormat 换成 DateTimeFormatter。
1.7volatile 与 synchronized 区别?▶
  • volatile:保证可见性、有序性,不保证原子性。底层内存屏障,写后刷回主内存,读前从主内存加载。
  • synchronized:保证原子性、可见性、有序性。代码块用 monitorenter/monitorexit,方法用 ACC_SYNCHRONIZED。
  • 锁升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁。
场景:volatile 适合状态标志、双检锁单例的 instance;synchronized 适合需要原子性的复合操作如 i++。
1.8JMM 与 happens-before?▶

JMM定义了线程与主内存的交互:每个线程有工作内存,变量从主内存拷贝副本操作,再写回主内存。

happens-before 八条规则
  • 程序顺序:同线程内前面 hb 后面。
  • 监视器锁:解锁 hb 后续加锁。
  • volatile:写 hb 后续读。
  • 线程启动:start() hb 线程内所有操作。
  • 线程终止:线程内所有操作 hb 其他线程检测到终止。
  • 线程中断、对象终结、传递性。
1.9CAS 与 ABA 问题?▶

CAS:比较并交换,V==A 时更新为 B,由 CPU 指令保证原子性。

三大问题
  • ABA:值从 A 变 B 又变 A,CAS 察觉不到。解决用 AtomicStampedReference 加版本号。
  • 自旋开销:失败一直重试,CPU 空转。用 LongAdder 分段减少竞争。
  • 只能保证单个变量:多变量用 AtomicReference 封装。
1.10AQS 的原理?▶

核心:volatile int state + CLH 双向队列。ReentrantLock、Semaphore、CountDownLatch 都基于 AQS。

加锁流程
  1. CAS 修改 state,成功则获取锁。
  2. 失败封装成 Node 入队,LockSupport.park 阻塞。
  3. 前驱释放后 unpark 唤醒后继。

两种模式:独占(ReentrantLock)和共享(Semaphore、CountDownLatch)。

1.11线程池 7 大参数与执行流程?▶

7 参数:corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。

执行流程
  1. 线程数 < core,创建核心线程。
  2. 核心满,任务入队列。
  3. 队列满,创建非核心线程。
  4. 达到 max,触发拒绝策略。

拒绝策略:Abort(抛异常)、CallerRuns(调用者执行,反压)、Discard(丢弃)、DiscardOldest(丢最老的)。

线程数:CPU 密集 N+1;IO 密集 2N 或 QPS×耗时;最终以压测为准。

项目结合:简历筛选用自定义线程池 resume-parse,CallerRunsPolicy 降速不丢任务。
1.12多线程处理密集任务怎么做?▶

方案:分批读取 + 自定义线程池 + CompletableFuture 并行 + 汇总落库。

  1. DB 分批读简历,每批 100 条。
  2. 提交线程池,supplyAsync 并行解析、匹配、评分。
  3. allOf 等待全部完成,汇总批量落库。

注意:子线程事务失效需编程式事务;异常必须捕获;结果落库用唯一索引 + Redis 去重保证幂等;控制并发度防打爆连接池。

效果:招聘系统筛选从分钟级降到秒级,工作量降低约 40%。
1.13ThreadLocal 原理与内存泄漏?▶

原理:每个 Thread 有 ThreadLocalMap,key 是 ThreadLocal 弱引用,value 强引用。get/set 操作当前线程自己的 map,天然隔离。

泄漏原因:ThreadLocal 被 GC 后 key 变 null,value 无法访问也无法释放;线程池场景下线程长期存活,泄漏累积。

解决:用完必须 remove(),通常放 finally;ThreadLocal 定义为 static final。

应用:用户上下文、traceId、事务连接绑定。

1.14死锁条件与排查?▶

四个条件:互斥、请求与保持、不可剥夺、循环等待。

预防:统一加锁顺序;tryLock 超时;减少锁粒度。

排查:jstack <pid> 输出 "Found one Java-level deadlock",列出线程、锁对象、等待关系。jconsole 也能检测。

1.15synchronized 锁升级过程?▶
  • 偏向锁:一个线程反复获取,把线程 ID 记在 Mark Word,之后同线程直接通过。JDK15 后废弃。
  • 轻量级锁:第二个线程竞争时升级,线程在栈帧建 Lock Record,CAS 指向它,适合竞争不激烈。
  • 重量级锁:CAS 自旋失败后升级,基于 OS mutex,未获取的线程挂起。

锁状态在 Mark Word 的 2 位标志:01 无锁/偏向、00 轻量级、10 重量级、11 GC。

1.16ReentrantLock 与 synchronized 区别?▶
维度synchronizedReentrantLock
实现JVM 关键字JUC 类,基于 AQS
释放自动手动 unlock(finally)
可中断否lockInterruptibly 支持
超时否tryLock(timeout) 支持
公平性非公平可选公平/非公平
条件变量一个 wait/notify多个 Condition
1.17读写锁 ReadWriteLock 的原理?▶

分离读锁和写锁:读读不互斥、读写互斥、写写互斥。AQS 的 state 高 16 位表示读锁数量,低 16 位表示写锁重入次数。

适合读多写少的缓存场景,但要注意写饥饿——大量读可能让写线程一直拿不到锁。StampedLock 提供乐观读,性能更好。

1.18乐观锁与悲观锁的区别?▶
  • 悲观锁:假设一定冲突,先加锁。synchronized、Lock、select for update。适合写多。
  • 乐观锁:假设冲突少,先操作后校验。CAS、version 字段。适合读多。
update product 
set stock = stock - 1, version = version + 1 
where id = #{id} and version = #{version}
1.19并发容器有哪些?▶
  • ConcurrentHashMap:JDK8 用 CAS + synchronized 锁桶头。
  • CopyOnWriteArrayList:写时复制,读多写少。
  • ConcurrentLinkedQueue:CAS 无锁队列。
  • BlockingQueue:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue、DelayQueue。
  • LongAdder:分段累加,高并发计数优于 AtomicLong。
2

JVM 虚拟机

2.1JVM 内存区域划分?▶
  • 线程私有:程序计数器、虚拟机栈、本地方法栈。
  • 线程共享:堆、方法区(JDK8 后元空间)。
  • 堆分区:新生代(Eden + 2 Survivor 8:1:1)、老年代 1:2。

常见 OOM:堆溢出、元空间溢出、栈溢出、直接内存溢出。

2.2如何判断对象可回收?▶

引用计数法无法解决循环引用,JVM 不用。

可达性分析:从 GC Roots 出发不可达即可回收。

GC Roots:栈局部变量、静态变量、常量、本地方法栈、活跃线程、同步锁对象。

2.3垃圾回收算法与分代?▶

三大算法:标记-清除(碎片)、标记-复制(浪费空间)、标记-整理(移动成本)。

分代:新生代用复制,老年代用标记-清除/整理。晋升条件:年龄 15、Survivor 放不下、大对象直接进老年代。

2.4常见垃圾收集器?▶
  • Serial:单线程,客户端。
  • Parallel:多线程吞吐量优先,JDK8 默认。
  • CMS:并发标记清除,低停顿,有碎片,JDK9 废弃。
  • G1:分 Region,可预测停顿,JDK9 后默认。
  • ZGC:染色指针,停顿 <10ms,大堆。
2.5类加载过程与双亲委派?▶

过程:加载 → 验证 → 准备 → 解析 → 初始化。

双亲委派:先交父加载器,保证核心类安全、避免重复加载。

打破:SPI(线程上下文类加载器)、Tomcat 隔离、OSGi。

2.6OOM / CPU 飙高怎么排查?▶
CPU 飙高
  1. top 找进程 PID。
  2. top -Hp pid 找线程 TID。
  3. printf "%x" tid 转十六进制。
  4. jstack pid | grep -A 30 十六进制 定位代码。
OOM

启动加 -XX:+HeapDumpOnOutOfMemoryError,用 MAT 分析支配树。工具:jps、jstat、jmap、jstack、Arthas。

3

Spring / SpringBoot / SpringMVC

3.1IoC 和 AOP 的理解?▶

IoC:控制反转,对象创建和依赖注入交给容器。DI 是具体实现。

AOP:面向切面,日志、事务、权限、缓存从业务抽离。底层 JDK 动态代理(有接口)+ CGLIB(无接口)。

项目结合:外包系统用自定义注解 + AOP 记录操作日志、接口耗时、数据权限校验。
3.2Bean 生命周期?▶

实例化 → 属性注入 → Aware 接口 → BeanPostProcessor 前置 → InitializingBean/@PostConstruct → BeanPostProcessor 后置(AOP 代理在此生成)→ 使用 → 销毁。

3.3循环依赖怎么解决?▶

三级缓存:singletonObjects、earlySingletonObjects、singletonFactories。

流程:创建 A → 实例化后把工厂放入三级 → 注入 B → 创建 B → B 注入 A 时从三级拿工厂生成早期引用 → B 完成 → A 完成。

限制:只解决单例 setter/字段注入,构造器注入和 prototype 无法解决。

3.4事务传播行为?▶
  • REQUIRED(默认):有则加入,无则新建。
  • REQUIRES_NEW:总是新建,挂起当前。
  • NESTED:嵌套,内层可独立回滚。
  • 其他:SUPPORTS、NOT_SUPPORTED、MANDATORY、NEVER。
3.5事务失效场景?▶
  • 方法非 public。
  • 自调用(this 调用),绕过代理。
  • 异常被 catch 未抛出。
  • 抛受检异常但未配 rollbackFor。
  • 数据库引擎不支持(MyISAM)。
  • 多线程中调用。
3.6SpringBoot 自动装配原理?▶

@SpringBootApplication → @EnableAutoConfiguration → 读取 spring.factories 或 AutoConfiguration.imports → 条件注解筛选(@ConditionalOnClass、@ConditionalOnMissingBean)→ 注入 Bean。

4

MySQL 与 SQL 优化

4.1explain 关键字段?▶

重点看:type、key、rows、Extra。

  • type:system > const > eq_ref > ref > range > index > ALL。至少到 range/ref。
  • key:实际用的索引,null 表示没用。
  • rows:预估扫描行数,越小越好。
  • Extra:Using index 好;Using filesort、Using temporary 需优化。
4.2索引失效场景?▶
  • 对索引列用函数:where date(create_time)='2024-01-01'。
  • 隐式类型转换:字符串字段传数字。
  • 前导模糊:like '%关键词'。
  • or 部分无索引。
  • 不满足最左前缀。
  • 范围条件后索引失效:a=1 and b>2 and c=3,c 用不到。
4.3数据库深分页怎么优化?▶

慢的原因:limit 100000,20 会扫描并丢弃前 100000 行。

  • 游标分页:where id > #{lastId} order by id limit 20。
  • 延迟关联:先查主键再 join 回表。
  • 覆盖索引:先查主键再回表。
  • 业务限制:禁止跳页,只允许下一页。
  • 架构:搜索走 ES,冷数据归档。
项目结合:考勤、订单、冷链出入库记录列表都用游标分页 + 延迟关联。
4.4事务隔离级别与 MVCC?▶

ACID:原子性、一致性、隔离性、持久性。

四种隔离级别:读未提交、读已提交、可重复读(MySQL 默认)、串行化。

问题:脏读、不可重复读、幻读。

MVCC:undo log 版本链 + ReadView。RC 每次查询生成 ReadView,RR 首次生成并复用。解决不可重复读,幻读靠间隙锁。

4.5B+ 树为什么适合做索引?▶

对比 B 树:B+ 非叶子只存键,树矮 IO 少;叶子链表连接,范围查询快。

对比哈希:哈希等值 O(1),但不支持范围、排序、最左前缀。

4.6联合索引最左前缀原则?▶

联合索引 (a,b,c),查询条件必须从 a 开始连续匹配。

  • a=1:用 a。
  • a=1 and b=2:用 a、b。
  • b=2 and c=3:不用。
  • a=1 and b>2 and c=3:用 a、b,c 用不到。
4.7慢 SQL 如何定位与优化?▶

定位:慢查询日志、mysqldumpslow、pt-query-digest、performance_schema、explain。

优化:联合索引、覆盖索引、索引下推;子查询改 join、延迟关联、分页优化;减少回表;读写分离、缓存、归档、分库分表。

4.8主从复制原理与延迟解决?▶

主库写 binlog → 从库 IO 线程拉取 → relay log → SQL 线程回放。

延迟解决:并行复制(MTS)、拆大事务、半同步、强一致读走主库。

5

Redis 缓存

5.1Redis 数据类型与场景?▶
  • String:缓存、计数器、分布式锁。
  • Hash:对象属性、购物车。
  • List:消息队列、最新列表。
  • Set:去重、共同好友、抽奖。
  • ZSet:排行榜、延时队列、滑动窗口限流。
  • Bitmap/HyperLogLog/GEO/Stream:签到、UV、附近的人、消息队列。
5.2缓存穿透、击穿、雪崩?▶
  • 穿透:查不存在数据打 DB。解决:布隆过滤器、缓存空值、参数校验。
  • 击穿:热点 key 过期打 DB。解决:互斥锁重建、逻辑过期、热点永不过期。
  • 雪崩:大量 key 同时过期或 Redis 宕机。解决:过期时间加随机、多级缓存、集群、熔断降级。
5.3缓存与数据库一致性?▶

推荐:先更新 DB,再删缓存(Cache Aside)。

加强:延迟双删、Canal 订阅 binlog 异步删、分布式锁、过期时间兜底。

5.4Redis 分布式锁实现与坑?▶

加锁:SET key value NX PX 30000,value 唯一。

释放:Lua 脚本比较 value 再删,防误删。

续期:Redisson 看门狗,默认 30 秒,每 10 秒续期。

坑:锁过期业务未完成、误删、主从切换丢锁、不可重入。

5.5Redis 为什么快?▶
  • 纯内存操作。
  • IO 多路复用(epoll)。
  • 单线程命令执行,无锁竞争。
  • 高效数据结构。
  • Redis 6.0 后网络 IO 多线程,命令执行仍单线程。
5.6过期删除与内存淘汰策略?▶

过期删除:惰性删除 + 定期删除。

淘汰策略:noeviction、allkeys-lru/lfu/random、volatile-lru/lfu/random/ttl。缓存推荐 allkeys-lru。

5.7主从、哨兵、集群区别?▶
  • 主从:读写分离,手动故障转移。
  • 哨兵:自动故障转移 + 监控。
  • Cluster:16384 槽分片,水平扩展。
5.8大 key / 热 key 怎么处理?▶

大 key:拆分、Hash 分片、unlink 异步删除、scan。

热 key:本地缓存、多级缓存、key 加随机后缀、读写分离。

6

分布式基础

6.1CAP 与 BASE?▶

CAP:一致性、可用性、分区容错,分布式必须 P,取舍 C/A。

CP:ZK、Nacos 持久实例;AP:Eureka、Nacos 临时实例。

BASE:基本可用、软状态、最终一致。

6.2分布式事务方案?▶
  • 2PC/3PC:强一致,阻塞、性能差。
  • TCC:Try-Confirm-Cancel,侵入大。
  • 本地消息表:业务与消息同事务,定时补偿。
  • MQ 事务消息:RocketMQ 半消息 + 回查。
  • Saga:长事务拆本地事务 + 补偿。
  • 最大努力通知:支付回调。
6.3幂等设计方案?▶
  • 唯一索引:DB 层兜底。
  • 去重表:记录业务唯一标识。
  • Redis Token:请求前获取,处理时原子删除。
  • 状态机:只允许合法状态流转。
  • 乐观锁:version 字段。
  • 分布式锁:同业务 ID 串行。
6.4限流算法与实现?▶
  • 固定窗口:INCR + EXPIRE,简单但有临界问题。
  • 滑动窗口:ZSet 存时间戳,Lua 保证原子。
  • 漏桶:恒定速率流出。
  • 令牌桶:允许突发,Guava RateLimiter。

组件:Guava、Redis+Lua、Nginx limit_req、Sentinel。

6.5延时任务实现方式?▶
  • RabbitMQ TTL + DLX。
  • Redis ZSet:score 存时间戳。
  • Redisson DelayedQueue。
  • 时间轮:Netty HashedWheelTimer。
  • XXL-JOB、Quartz。
6.6分布式 ID 方案?▶

UUID、数据库自增、号段模式、雪花算法、Redis INCR。

雪花:1 符号 + 41 时间 + 10 机器 + 12 序列。趋势递增,需解决时钟回拨。

7

微服务架构与组件

7.1微服务拆分原则?▶
  • 单一职责:一个服务只做一件事。
  • DDD 限界上下文划分。
  • 高内聚低耦合。
  • 独立部署、独立数据。
  • 演进式拆分:先单体,痛点出现再拆。
7.2服务雪崩与防护?▶

雪崩:下游故障导致上游线程耗尽,连锁崩溃。

防护:超时控制、熔断、降级、隔离、限流、重试(幂等)、缓存。

7.3熔断、降级、限流的区别?▶
  • 限流:入口控流量,超阈值拒绝(预防)。
  • 熔断:下游故障快速失败,给恢复时间(自保)。
  • 降级:返回兜底结果(兜底)。
7.4Nacos 注册中心原理?AP 还是 CP?▶

临时实例:心跳保活,AP(Distro),优先可用。

持久实例:主动探测,CP(Raft),优先一致。

推拉结合:客户端定时拉取 + 服务端 UDP 推送变更。

健康检查:5 秒心跳,15 秒未收到标记不健康,30 秒剔除。

7.5Nacos 配置动态刷新原理?▶

长轮询:客户端发起 30 秒长轮询,服务端 hold 住。

变更通知:配置变化时立即响应,客户端拉取最新。

本地快照:客户端缓存配置,服务端不可用仍能启动。

刷新:@RefreshScope、@ConfigurationProperties。

7.6OpenFeign 原理?▶

扫描 @FeignClient → 动态代理生成实现 → 注解解析 → 编码 → LoadBalancer 选实例 → HTTP 调用 → 解码。

超时:connectTimeout、readTimeout。

重试:默认关闭,写接口必须幂等才能重试。

优化:替换为 OkHttp 连接池,开启 GZIP。

7.7Gateway 核心概念与限流?▶

三大概念:Route、Predicate、Filter。

执行流程:请求 → HandlerMapping 匹配 → Pre 过滤器 → 转发下游 → Post 过滤器 → 响应。

限流:RequestRateLimiter + Redis 令牌桶。

注意:基于 WebFlux,不能引 spring-boot-starter-web。

7.8Sentinel 核心功能与原理?▶

功能:限流、熔断、降级、系统保护、热点参数、授权。

熔断状态机:关闭 → 打开 → 半开。

原理:SlotChain 责任链,依次执行 NodeSelector、ClusterBuilder、Statistic、Flow、Degrade。

7.9Seata 四种事务模式?▶
  • AT:无侵入,undo log 反向补偿,需主键。
  • TCC:Try-Confirm-Cancel,业务侵入大。
  • Saga:长事务拆本地事务,逆向补偿。
  • XA:数据库 XA,强一致性能差。

三角色:TC(协调者)、TM(管理者)、RM(资源管理者)。

7.10分布式链路追踪怎么做?▶

核心概念:TraceId、SpanId、ParentSpanId。

传递方式:HTTP Header / MQ 属性透传,MDC + ThreadLocal 记录日志。

方案:Sleuth+Zipkin、SkyWalking(字节码增强,无侵入)。

7.11微服务如何做统一鉴权?▶

方案:网关统一鉴权 JWT/OAuth2,用户信息放 Header 透传。内部调用用内部 Token 或 mTLS。

权限模型:RBAC,注解 + AOP 接口级鉴权。

7.12微服务技术选型?▶
能力推荐
注册/配置Nacos
服务调用OpenFeign
网关Spring Cloud Gateway
熔断限流Sentinel
分布式事务Seata
链路追踪SkyWalking
消息队列RocketMQ / RabbitMQ
监控Prometheus + Grafana
8

RabbitMQ 消息队列

8.1MQ 作用与选型?▶

作用:异步解耦、削峰填谷、最终一致。

选型:RabbitMQ 低延迟可靠;Kafka 高吞吐;RocketMQ 事务/延迟消息。

8.2如何保证消息不丢?▶
  • 生产者:Confirm + Return 回调,失败重试。
  • Broker:交换机、队列、消息都持久化。
  • 消费者:手动 ACK,失败进死信。
  • 兜底:本地消息表 + 定时补偿。
8.3如何保证消息不重复消费?▶

MQ 只能保证 at-least-once,需业务幂等:消息带唯一 ID;Redis SETNX 或唯一索引去重;状态机控制流转。

8.4消息积压怎么处理?▶
  • 临时扩容消费者。
  • 批量消费。
  • 耗时操作异步化。
  • 紧急转临时队列。
  • 预防:队列深度监控 + 告警。
9

设计模式实践

9.1项目中用过哪些设计模式?▶
  • 策略 + 工厂:支付、推送、简历匹配。
  • 状态:订单、合同、出入库状态。
  • 责任链:审批、校验、简历筛选规则链。
  • 模板方法:导入、对账。
  • 观察者:Spring 事件、MQ 通知。
  • 适配器:第三方支付、物流、IM 封装。
9.2策略 + 工厂在支付中的应用?▶

策略接口:PayStrategy,定义 pay()、refund()。

实现类:WechatPay、Alipay、OfflinePay。

工厂:PayStrategyFactory 用 Map 缓存所有策略 Bean,按类型返回。

好处:新增渠道只需加实现类,符合开闭原则。

9.3责任链模式在简历筛选中的应用?▶

结构:抽象 Handler 持有 next,每个节点处理自己的规则。

规则链:学历 → 工作年限 → 技能匹配 → 匹配度评分。

好处:规则可插拔,新增不影响其他节点。

10

Docker 与 Kubernetes

10.1容器和虚拟机的区别?▶
维度容器虚拟机
隔离进程级硬件级
OS共享内核独立 OS
启动秒级分钟级
资源MB 级GB 级
隔离性较弱强
10.2Docker 的底层原理?▶
  • Namespace:资源隔离(PID、NET、IPC、MNT、UTS、USER、CGROUP)。
  • Cgroup:资源限制(CPU、内存、IO)。
  • UnionFS:镜像分层,OverlayFS/AUFS。

调用链:docker CLI → dockerd → containerd → shim → runc → 容器进程。

10.3镜像分层与 Copy-on-Write?▶

分层:镜像由多个只读层组成,每条 Dockerfile 指令一层,共享底层节省空间。

CoW:容器读文件直接读下层;写文件先把文件复制到可写层再改,下层保持只读。

10.4CMD 和 ENTRYPOINT 的区别?▶
  • CMD:默认命令,docker run 后面的参数会覆盖。
  • ENTRYPOINT:入口命令,不会被覆盖,参数追加。
ENTRYPOINT ["java", "-jar", "/app.jar"]
CMD ["--spring.profiles.active=prod"]
10.5什么是多阶段构建?▶

一个 Dockerfile 写多个 FROM,后面的阶段可以引用前面阶段的产物。构建阶段用完整镜像,运行阶段只用 JRE。

FROM maven:3.9-jdk-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

效果:从 600MB 降到 150MB 左右。

10.6Docker 网络模式?▶
  • bridge(默认):docker0 网桥,NAT 访问外网。
  • host:共享宿主机网络,性能好但端口冲突。
  • none:无网络。
  • container:共享另一容器网络。
  • 自定义 bridge:支持 DNS 服务发现(推荐)。
10.7数据卷三种挂载方式的区别?▶
  • Volume:Docker 管理,存在 /var/lib/docker/volumes,推荐持久化。
  • Bind Mount:挂宿主机任意路径,方便调试。
  • tmpfs:内存挂载,重启丢失。
10.8容器 OOM Kill 怎么处理?▶

退出码 137 通常是 OOM。解决:

  • 调整内存限制 --memory=2g。
  • JVM 感知容器:-XX:MaxRAMPercentage=75.0。
  • 排查内存泄漏:dump 堆分析。
  • 限制应用内存:本地缓存加大小限制。
10.9K8s 核心组件?▶
控制平面
  • kube-apiserver:API 入口。
  • etcd:KV 存储,保存集群状态。
  • kube-scheduler:调度 Pod。
  • kube-controller-manager:运行控制器。
工作节点
  • kubelet:节点代理,管理 Pod。
  • kube-proxy:网络代理,Service 负载均衡。
  • Container Runtime:containerd、CRI-O。
10.10Pod、Deployment、Service 的关系?▶

Ingress → Service → Deployment → ReplicaSet → Pod → Container。

  • Pod:最小调度单位,一个或多个容器共享网络存储。
  • Deployment:管理副本数和滚动更新。
  • Service:稳定访问入口,ClusterIP/NodePort/LoadBalancer。
  • Ingress:七层入口,HTTP/HTTPS 路由。
10.11K8s 探针有哪几种?▶
  • livenessProbe:失败重启容器,检测死锁。
  • readinessProbe:失败从 Service 摘除,不接收流量。
  • startupProbe:慢启动应用,成功后其他探针生效。
坑:liveness 不能依赖外部服务(如 DB),否则 DB 抖动会反复重启应用。
10.12K8s 滚动更新与回滚?▶
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0
kubectl set image deployment/myapp myapp=myapp:2.0
kubectl rollout status deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=2
11

LangChain4j 与 AI 应用

11.1LangChain4j 是什么?解决什么问题?▶

专为 Java 开发者设计的 LLM 集成框架,统一 API 集成 OpenAI、通义千问、Ollama 等模型。

解决的问题
  • 屏蔽模型提供商 API 差异。
  • 声明式 AI Service,只写接口。
  • 内置 RAG 流水线。
  • Function Calling 工具调用。
  • ChatMemory 多轮对话。
11.2AiServices 是什么?怎么用?▶

高层 API,定义 Java 接口,框架通过动态代理自动生成实现。

  1. 接口方法用 @SystemMessage 和 @UserMessage 声明提示词。
  2. AiServices.builder(Interface.class) 绑定 ChatModel、Memory、Retriever、Tools。
  3. 注入接口直接调用。
类比:AI Service 之于大模型,像 Spring Data JPA 之于数据库——只定义接口,不用写实现。
11.3RAG 是什么?LangChain4j 怎么实现?▶

RAG(检索增强生成):先检索相关文档片段,再拼到提示词中让模型基于真实文档回答,避免幻觉。

四步流水线
  1. 文档摄入:加载 Markdown、PDF 等。
  2. 向量化存储:EmbeddingModel 转向量,存 EmbeddingStore。
  3. 检索:问题向量化,从向量库检索 Top-K。
  4. 生成:片段 + 问题发给 ChatModel 生成回答。
11.4Function Calling / Tools 怎么用?▶

在 Java 方法上加 @Tool 注解,在 AI Service 中指定工具类,框架自动处理调用循环。

流程:LLM 返回 toolExecutionRequests → 执行工具 → 结果封装成 ToolExecutionResultMessage → 再发给模型 → 模型生成最终回答。

项目结合:AI 简历筛选定义 @Tool 方法查询岗位信息、候选人历史,让模型基于真实数据判断。
11.5ChatMemory 与 MemoryId?▶

ChatMemory 管理多轮对话上下文。

MemoryId 会话隔离标识,方法参数上加 @MemoryId,不同用户对话互不干扰。

持久化:用 Redis 作为 ChatMemoryStore,重启后恢复上下文。

11.6AI 简历筛选项目中 LangChain4j 怎么用的?▶
  1. 定义 AI Service 接口,接收简历文本和岗位描述。
  2. @SystemMessage 设定招聘经理角色和评分标准。
  3. @UserMessage 传入简历和 JD,输出结构化评分。
  4. 返回 CvReview 对象(score + feedback)。

工程化:线程池批量并行,Redis 去重 + 唯一索引幂等,异常重试。

效果:筛选工作量降低约 40%。

追问准备:幻觉?结构化输出 + 规则校验 + 人工复核。Token 成本?截断 + 缓存 + 小模型兜底。并发?Semaphore 限制。
11.7RAG 检索效果不好怎么优化?▶
  • 调整切片大小(500-1000 字符,重叠 10%-20%)。
  • 调整 Top-K(3-10)。
  • 设置相似度阈值 minScore。
  • 元数据过滤。
  • 重排序 ReRankingModel。
  • 查询改写。
  • 混合检索(向量 + 关键词)。
11.8LangChain4j 和 Spring AI 怎么选?▶
  • Spring AI:与 Spring Boot 无缝集成,API 简洁,适合快速开发。
  • LangChain4j:更灵活,支持复杂 RAG、Agent、多轮对话,适合复杂 AI 应用。
12

计算机网络

12.1TCP 三次握手与四次挥手?▶

三次握手:SYN → SYN+ACK → ACK,确认双方收发能力。

四次挥手:FIN → ACK → FIN → ACK,全双工需分别关闭。

TIME_WAIT:2MSL,保证最后 ACK 到达,防止旧连接数据混淆。

12.2HTTP 与 HTTPS 区别?▶

HTTPS = HTTP + TLS/SSL,加密传输,防篡改防窃听。

握手:非对称加密交换密钥,之后对称加密通信。端口 80 / 443。

12.3IO 多路复用 select/poll/epoll?▶
  • select:数组,1024 限制,O(n) 轮询。
  • poll:链表,无上限,仍 O(n)。
  • epoll:红黑树 + 就绪链表,O(1) 回调,适合高并发。

Redis、Nginx、Netty 都用 epoll。

13

数据结构与算法

13.1常见排序算法复杂度?▶
  • 冒泡/选择/插入:O(n²)。
  • 快排:平均 O(nlogn),最坏 O(n²),不稳定。
  • 归并:O(nlogn),稳定,需额外空间。
  • 堆排:O(nlogn),不稳定。
13.2LRU 缓存怎么实现?▶

HashMap + 双向链表,O(1) 查找和增删。Java 可用 LinkedHashMap,重写 removeEldestEntry。

13.3海量数据 Top K 怎么解决?▶
  • 小顶堆:维护 K 个元素,O(n log K)。
  • 分治 + 哈希:大文件拆分到多个小文件,分别求 Top K 再合并。
13.4链表反转与环检测?▶

反转:pre/cur/next 三指针迭代。

环检测:快慢指针,相遇则有环;相遇后一指针回头,再次相遇即入口。

14

项目话术与速记

14.1项目介绍标准话术模板?▶

模板:背景是 X,数据量/QPS 是 Y,痛点是 Z;我用 A 技术解决 B 问题,指标提升 C%。

  • 招聘系统:简历筛选人工工作量大。线程池并行 + LangChain4j + Redis 去重,筛选工作量降低 40%。
  • 外包管理:考勤打卡重复、合同状态乱。Redisson 锁 + 唯一索引 + 状态机,效率提升 30%。
  • 冷链仓储:出入库深分页慢。游标分页 + 延迟关联 + 覆盖索引,查询性能提升。
  • 本地生活:支付回调重复。唯一索引 + 状态机 + Redis Token 保证幂等。
14.2设计一个秒杀系统?▶
  • 前端:按钮置灰、验证码。
  • 网关:限流、黑名单。
  • Redis:库存预热、Lua 原子扣减、SETNX 防重。
  • MQ:异步下单,削峰填谷。
  • DB:唯一索引防超卖,异步落库。
  • 兜底:限流降级、库存回滚、对账补偿。
14.3线上接口变慢怎么排查?▶
  • 链路追踪定位慢服务。
  • Arthas trace 定位慢方法。
  • 检查慢 SQL、Redis 大 key、线程池满、GC 频繁、下游超时。
  • 工具:SkyWalking、Arthas、Prometheus、慢查询日志。
14.4一句话速记合集▶
  • volatile:可见有序不原子。
  • synchronized:原子可见有序,锁升级。
  • 线程池:核心 → 队列 → 最大 → 拒绝。
  • 深分页:游标、延迟关联、覆盖索引。
  • type 排序:system > const > eq_ref > ref > range > index > ALL。
  • 索引失效:函数、隐式转换、前导模糊、最左前缀。
  • 缓存三兄弟:穿透、击穿、雪崩。
  • 缓存一致:先更新 DB,再删缓存,延迟双删。
  • 分布式锁:SET NX PX + Lua 释放 + 看门狗。
  • 幂等:唯一索引、去重表、Redis Token、状态机。
  • 限流:固定窗口、滑动窗口、漏桶、令牌桶。
  • 延时任务:TTL+DLX、Redis ZSet、时间轮、XXL-JOB。
  • Nacos:临时 AP,持久 CP。
  • 配置刷新:长轮询 + 本地快照 + @RefreshScope。
  • Feign:动态代理 + 负载均衡 + HTTP。
  • Gateway:Route + Predicate + Filter,WebFlux。
  • Sentinel:限流、熔断、降级,SlotChain。
  • 雪崩防护:超时、熔断、降级、隔离、限流。
  • Seata:AT 无侵入,TC/TM/RM。
  • 雪花:1 + 41 + 10 + 12。
  • MQ 不丢:Confirm + 持久化 + 手动 ACK。
  • MQ 不重:唯一 ID + 幂等消费。
  • Docker:Namespace + Cgroup + UnionFS。
  • 镜像分层:COPY/RUN 每步一层,共享底层。
  • 多阶段构建:构建和运行分离,600MB 降到 100MB。
  • K8s:Pod + Deployment + Service + Ingress,探针三件套。
  • LangChain4j:AiServices 接口,RAG 检索增强,@Tool 工具调用。