6 年 Java 后端开发经验,深耕珠宝 MES/ERP 近三年,主导订单/排产/仓储全链路模块, 服务 40+ 家工厂。2025 年起任项目负责人,带领 4 人团队统筹多模块迭代交付。主导团队 AI 工具从 0 到 1 落地 (Claude Code CLI + Skill/MCP 沉淀团队知识),助力团队效率提升。
数据结构:数组 + 链表 + 红黑树。
put 流程:对 key 求 hashCode() → 高 16 位异或低 16 位(扰动函数)→ (n-1) & hash 定位桶位 → 桶为空直接放,不为空判断是链表还是红黑树 → 链表尾插并检查是否 ≥8 转树(数组容量需 ≥64)。
JDK 1.8 优化:优化 头插 → 尾插(避免 resize 时链表死循环);优化 引入红黑树,链表 ≥8 且数组 ≥64 时转树,退化为链表阈值 6;扰动函数从 4 次异或简化为 1 次。
扩容:默认容量 16,负载因子 0.75。扩容时容量翻倍,rehash 利用二进制特性判断高位是 0(留在原位)还是 1(新位置 = 原位置 + 旧容量)。
注意 HashMap 线程不安全,并发 put 可能导致数据丢失或链表死循环(1.7)。并发场景用 ConcurrentHashMap。
JDK 1.7:分段锁(Segment),默认 16 段,每段独立 ReentrantLock,并发度 = 段数。put 时定位 Segment → lock() → 头插法。
JDK 1.8 大改:优化 抛弃分段锁,改用 CAS + synchronized 锁桶头节点。数组 + 链表 + 红黑树结构,与 HashMap 一致。
put 流程(1.8):计算 hash → 自旋:若桶为 null 则 CAS 放入 → 若桶头节点 hash==MOVED(-1)则帮忙扩容(helpTransfer)→ 否则 synchronized 锁住桶头节点执行插入。
size 计数:用 CounterCell 数组分摊竞争(类似 LongAdder),避免 CAS 自旋消耗。
与 Hashtable 的区别:Hashtable 锁整个表,put/get 全串行化;ConcurrentHashMap 锁粒度细化到桶级别,读操作不加锁(Node 的 val/next 用 volatile)。
运行时数据区:堆(对象实例,GC 主战场)、方法区/元空间(类信息、常量、静态变量)、虚拟机栈(栈帧:局部变量表 + 操作数栈 + 动态链接 + 返回地址)、本地方法栈、程序计数器。
堆分代:新生代(Eden + S0 + S1,默认 8:1:1)→ Minor GC 采用复制算法;老年代 → Major/Full GC 采用标记-清除或标记-整理。
GC 算法:标记-清除(碎片化)、标记-整理(移动开销)、复制(浪费空间但快,适合新生代)。现代 JVM 默认 G1:将堆划分为等大 Region,优先回收垃圾最多的 Region(Garbage First),通过 Remembered Set 避免全堆扫描。
GC 触发条件:Eden 满 → Minor GC;老年代空间不足 → Full GC;System.gc() 建议但不保证;元空间不足 → Full GC。
实战 线上 129 万条 Redis List 全量反序列化 → 2.18GB 堆 → Full GC 频繁 → 最终 OOM。解法:限制 range 读取长度 + 定期 trim + 修正永不过期的 key。
7 个参数:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(空闲存活时间)、unit(时间单位)、workQueue(阻塞队列)、threadFactory(线程工厂)、rejectedExecutionHandler(拒绝策略)。
执行流程:核心线程未满 → 创建核心线程执行;核心线程满 → 任务入队;队列满且最大线程未满 → 创建临时线程;全部满 → 触发拒绝策略。
拒绝策略:AbortPolicy(抛异常,默认)、CallerRunsPolicy(调用者线程执行)、DiscardPolicy(静默丢弃)、DiscardOldestPolicy(丢弃队首旧任务再重试)。
Tomcat 线程池 与 JDK 不同:先扩到 max 再入队,优先扩线程应对突发,而非 JDK 的「先核心 → 再入队 → 再扩」。
最佳实践:不要用 Executors 快捷方法(newFixedThreadPool 无界队列 OOM、newCachedThreadPool 无限线程)。自定义线程池,根据 IO 密集型(2N+1)还是 CPU 密集型(N+1)设置核心线程数。
B+Tree vs 其他:Hash 索引不支持范围查询、排序、最左匹配;二叉树退化为链表;AVL/红黑树高度大(磁盘 IO 次数多);B-Tree 非叶子节点存储数据 → 单页存储索引项少 → 树更高。
B+Tree 优势:① 所有数据存叶子节点,非叶子只存索引 → 单页索引项多 → 树更矮 → IO 更少;② 叶子节点形成有序双向链表 → 范围查询顺链扫即可;③ 查询任何数据路径等长,稳定。
聚簇 vs 非聚簇:InnoDB 主键索引叶子存完整行数据(聚簇),二级索引叶子存主键值 → 回表。MyISAM 索引叶子存数据地址,数据文件与索引文件分离。
最左前缀原则:联合索引 (a, b, c) 相当于建了 a、a,b、a,b,c 三个索引。跳过 a 直接用 b 不走索引。a like '%xxx' 不走,a like 'xxx%' 可以。
实战 多业务共用底表累积 3000 万行,部分业务依赖底表筛选效率低下。一次 ALTER TABLE 锁表 40 分钟触发全业务阻塞,推动按业务拆分,核心查询从 40 秒+ 优化至 2~3 秒。