面灵AI→

XTransfer 后端社招一面:线程池、Full GC 与 Redis 缓存一致性

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 自我介绍。
  2. 在上家公司有什么收获?
  3. 平时用过什么 AI 工具?
  4. 用过哪些设计模式?结合实际场景介绍一下。
  5. 线程池的核心参数有哪些?核心线程和最大线程有什么区别?
  6. 为什么不建议使用 JDK 提供的线程池?
  7. JVM 的垃圾回收机制是怎样的?内存飙高怎么办?
  8. 什么是 Full GC?为什么会发生 Full GC?老年代不足说明什么?
  9. 悲观锁和乐观锁分别适用什么场景?
  10. synchronized 与 ReentrantLock 有什么区别?
  11. Redis 除了分布式锁还能做哪些缓存场景?如何保证缓存一致?
  12. 大 key 问题和热 key 问题分别怎么处理?
  13. MySQL 的慢 SQL 怎么优化?
  14. 索引在什么时候需要加?
  15. 手撕:无重复字符的最长子串、最大数。

《参考解析》

线程池与不用 Executors 的原因:参数是 corePoolSize、maximumPoolSize、keepAliveTime、workQueue、threadFactory 和拒绝策略。提交顺序是先占满核心线程、再进队列、队列满才扩到最大线程数、仍满才拒绝。不用 Executors 是因为边界不清:FixedThreadPool 用无界队列会 OOM,CachedThreadPool 的最大线程数是 Integer.MAX_VALUE。

Full GC 与内存飙高:Full GC 多由老年代或元空间不足、晋升失败、显式 System.gc() 触发。老年代不足说明对象活得久或被长生命周期引用拽住,先怀疑无界缓存、只增不删的集合、ThreadLocal 忘记 remove。jstat -gcutil 看回收后能不能降,降不下来就是泄漏,再用 jmap 加 MAT 看引用链。

锁与缓存:悲观锁适合写多冲突高;乐观锁适合读多写少,用版本号和 CAS 重试。synchronized 是 JVM 内置、异常自动释放,ReentrantLock 多了公平锁、可中断和多个 Condition,代价是必须 finally 解锁。缓存一致性走 Cache Aside:更新库后删缓存而非更新缓存,删失败用延迟双删或订阅 binlog;大 key 拆分后 unlink 异步删,热 key 靠本地缓存和限流。

慢 SQL 与手撕:explain 看 type、key、rows、Extra,常见病因是索引列上做函数运算、隐式类型转换、深分页。索引加在高频且区分度高的列上。无重复最长子串用滑动窗口加哈希记上次位置;最大数按 a+b 与 b+a 排序。