面试现场:大厂Java岗,谢飞机登场
面试官(推了推眼镜):请做个自我介绍。
谢飞机:我叫谢飞机,擅长起飞,落地不太稳……但代码从不炸机!
第一轮:Java基础 & 集合框架
Q1:说说 HashMap 的底层结构?
谢飞机:数组 + 链表,JDK8 后链表长度超 8 变红黑树!
面试官:不错,有点东西。
Q2:那 ConcurrentHashMap 如何保证线程安全?
谢飞机:synchronized 锁整个 map!
面试官:……JDK7 是分段锁,JDK8 是 CAS + synchronized 控制桶头节点,你这锁全表,系统得卡成PPT。
Q3:ArrayList 和 LinkedList 区别?
谢飞机:一个基于数组,查询快;一个基于链表,增删快!
面试官:还行,勉强过关。
第二轮:并发编程 & 中间件
Q4:线程池的核心参数有哪些?
谢飞机:corePoolSize、maxPoolSize、workQueue、threadFactory、handler!背过!
面试官:可以,那你来说说拒绝策略?
谢飞机:比如 AbortPolicy,就是直接干掉任务……哦不,抛异常!
面试官:还知道其他吗?
谢飞机:CallerRunsPolicy,让主线程自己跑……还有……还有……我运行一下脑子——超时了!
Q5:Redis 的持久化机制?
谢飞机:RDB 是拍快照,AOF 是记日志,append only!
面试官:那两者如何选择?
谢飞机:看脸……啊不是,看业务!数据重要用 AOF,性能优先用 RDB!
面试官:勉强及格。
第三轮:Spring生态 & 架构设计
Q6:SpringBoot 自动装配原理?
谢飞机:@EnableAutoConfiguration,扫描 META-INF/spring.factories,条件装配!
面试官:不错,有准备。
Q7:MyBatis #{} 和 ${} 区别?
谢飞机:#{} 防 SQL 注入,${} 拼接字符串,要小心XSS!
面试官:嗯,安全意识还可以。
Q8:DDD 中的聚合根是什么?
谢飞机:就是……很多模块聚在一起,像个领导一样管理大家……
面试官:……你这是团建吧?
Q9:Dubbo 的调用流程?
谢飞机:消费者找注册中心,拿到提供者地址,然后 RPC 调用,走的是 Netty!
面试官:还行,底层通信知道。
面试官(合上笔记本):今天就到这里,你的水平……我们回去讨论一下,回家等通知吧。
谢飞机(小声):等通知=没通知,又要重新起飞了……
参考答案详解
Q1:HashMap 底层结构
- JDK8 前:数组 + 链表
- JDK8 后:数组 + 链表 + 红黑树(链表长度 ≥ 8 且数组长度 ≥ 64)
- 扩容机制:负载因子 0.75,触发扩容为原容量 2 倍
- hash 冲突:通过扰动函数减少碰撞
Q2:ConcurrentHashMap 线程安全
- JDK7:Segment 分段锁,继承 ReentrantLock
- JDK8:CAS + synchronized 锁桶的头节点,降低锁粒度,性能更高
- 使用 volatile 保证可见性
Q3:ArrayList vs LinkedList
- ArrayList:基于动态数组,支持随机访问 O(1),扩容成本高,插入删除慢
- LinkedList:双向链表,插入删除 O(1),遍历慢,占用内存多(前后指针)
Q4:线程池核心参数
- corePoolSize:核心线程数
- maxPoolSize:最大线程数
- keepAliveTime:非核心线程空闲存活时间
- workQueue:任务队列(如 LinkedBlockingQueue)
- threadFactory:线程创建工厂
- handler:拒绝策略
Q5:线程池拒绝策略
- AbortPolicy:抛出 RejectedExecutionException(默认)
- CallerRunsPolicy:由提交任务的线程执行该任务
- DiscardPolicy:默默丢弃任务
- DiscardOldestPolicy:丢弃队列中最老的任务,重试提交当前任务
Q6:Redis 持久化
- RDB:定时快照,恢复快,可能丢失数据
- AOF:记录每条写命令,appendonly.aof 文件,可配置 fsync 策略(everysec 最常用)
- 混合使用:Redis 4.0+ 支持 AOF 重写时包含 RDB 格式数据
Q7:SpringBoot 自动装配
- @SpringBootApplication → @EnableAutoConfiguration
- SpringFactoriesLoader 加载 META-INF/spring.factories 中的自动配置类
- 条件注解:@ConditionalOnClass、@ConditionalOnMissingBean 等控制是否生效
Q8:MyBatis #{} 与 ${}
- #{}:预编译处理,PreparedStatement 参数占位,防 SQL 注入
- ${}:字符串拼接,直接替换,需手动过滤特殊字符,用于动态表名、排序字段等
Q9:DDD 聚合根(Aggregate Root)
- 聚合:一组相关对象的集合,作为一个数据修改单元
- 聚合根:聚合的根实体,外部只能通过聚合根访问内部对象
- 保证一致性边界,避免脏数据,常用于复杂业务模型设计
Q10:Dubbo 调用流程
- 服务提供者启动,注册服务到注册中心(Zookeeper/Nacos)
- 消费者启动,订阅注册中心服务列表
- 消费者通过代理发起调用,路由选择提供者
- Netty 进行网络通信,序列化传输
- 提供者执行方法,返回结果
- 支持负载均衡、熔断、限流等高级特性