面试官:Java线程池的核心参数了解吗?谢飞机:会用new Thread就不错了!

33 阅读5分钟

面试官:Java线程池的核心参数了解吗?谢飞机:会用new Thread就不错了!

面试官:请坐,先自我介绍一下吧。

谢飞机:面试官好,我叫谢飞机,三年Java开发经验,精通增删改查,熟悉Spring全家桶,会写Hello World。

面试官:嗯……那我们开始吧。


第一轮:基础技术考察

面试官:说说 ArrayList 和 LinkedList 的区别?

谢飞机:这个我会!ArrayList 是基于数组的,查询快,增删慢;LinkedList 是基于链表的,增删快,查询慢。

面试官:不错,理解到位。

面试官:HashMap 的底层结构是什么?

谢飞机:是数组 + 链表 + 红黑树。当链表长度超过8,并且数组长度大于64时,链表转成红黑树。

面试官:很好,继续。那 ConcurrentHashMap 如何保证线程安全?

谢飞机:1.7 用的是分段锁,1.8 改成了 CAS + synchronized。

面试官:可以,基本功扎实。


第二轮:并发与JVM

面试官:谈谈你对线程池的理解,核心参数有哪些?

谢飞机:线程池……就是用来管理线程的。核心参数嘛……有 corePoolSize、maximumPoolSize、workQueue……其他的我忘了,反正 new Thread() 也能跑。

面试官:……那你了解 JVM 内存模型吗?堆和栈的区别?

谢飞机:堆是放对象的,栈是放方法的。比如我 new 一个对象,就在堆里;方法里的局部变量就在栈里。

面试官:还行。那 GC 回收算法了解吗?

谢飞机:听说过,标记清除、复制算法……具体咋回事我也记不清了,反正 JVM 自动回收,不用管。

面试官:……


第三轮:微服务与中间件

面试官:Spring Bean 的作用域有哪些?

谢飞机:singleton 和 prototype!单例和原型。

面试官:不错。那 Spring Boot 自动装配原理?

谢飞机:靠 @SpringBootApplication 注解,里面有个 @EnableAutoConfiguration,它会去 META-INF/spring.factories 里加载配置类。

面试官:很好。Redis 用过哪些数据类型?

谢飞机:String、Hash、List……Set、ZSet!我都背过!

面试官:RabbitMQ 如何保证消息不丢失?

谢飞机:呃……持久化?生产者发完等确认?消费者手动ACK?好像是这样……

面试官:回答得比较模糊。最后一个问题:DDD 的核心概念是什么?

谢飞机:Domain……领域?其他我就不知道了,我们公司都直接三层架构 CRUD。

面试官:……


面试官:今天就到这里,你的基础还可以,但深度不够。回去等通知吧。

谢飞机:好的,谢谢面试官,我回去继续背八股文!


参考答案详解

1. ArrayList vs LinkedList

  • ArrayList:基于动态数组,支持随机访问(O(1)),扩容机制为1.5倍增长,适合读多写少。
  • LinkedList:基于双向链表,插入删除快(O(1)),但遍历慢(O(n)),占用更多内存(存储前后指针)。

2. HashMap 底层结构

  • JDK 1.8 后:数组 + 链表 + 红黑树。
  • 初始容量16,负载因子0.75,阈值12(16*0.75)。
  • 当链表长度≥8 且 数组长度≥64 时,链表转红黑树;反之,扩容。
  • 扰动函数减少哈希冲突,避免高位不变低位变化小导致的碰撞。

3. ConcurrentHashMap 线程安全实现

  • JDK 1.7:Segment 分段锁,每个 Segment 相当于一个小 HashMap,加锁粒度为 Segment。
  • JDK 1.8:抛弃 Segment,采用 CAS + synchronized。对数组元素头节点加锁,锁粒度更细,性能更高。
  • 使用 volatile 保证可见性,CAS 实现无锁更新 size 等操作。

4. 线程池核心参数

  • corePoolSize:核心线程数,常驻线程。
  • maximumPoolSize:最大线程数。
  • workQueue:阻塞队列,如 LinkedBlockingQueue、ArrayBlockingQueue。
  • keepAliveTime:非核心线程空闲存活时间。
  • threadFactory:线程工厂,可自定义线程命名等。
  • handler:拒绝策略,如 AbortPolicy、CallerRunsPolicy。

5. JVM 内存模型

  • 堆(Heap):存放对象实例,GC 主要区域,分为新生代(Eden、Survivor)、老年代。
  • 栈(Stack):每个线程私有,存放局部变量、方法调用、操作数栈等。方法执行完自动弹出。
  • 方法区:存放类信息、常量、静态变量(JDK 1.8 后为元空间 Metaspace)。
  • 程序计数器:记录当前线程执行的字节码行号。

6. GC 回收算法

  • 标记-清除(Mark-Sweep):标记存活对象,清除未标记对象。缺点:产生内存碎片。
  • 复制算法(Copying):将内存分为两块,每次使用一块,存活对象复制到另一块。用于新生代。
  • 标记-整理(Mark-Compact):标记后将存活对象向一端移动,清理边界外内存。用于老年代。
  • 分代收集:根据对象存活周期分代,新生代用复制,老年代用标记清除或标记整理。

7. Spring Bean 作用域

  • singleton:容器中唯一实例,全局共享。
  • prototype:每次获取都创建新实例。
  • request:每次 HTTP 请求创建一个实例(Web 环境)。
  • session:每个 HTTP Session 共享一个实例。
  • application:整个 ServletContext 生命周期内共享。

8. Spring Boot 自动装配原理

  • @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
  • @EnableAutoConfiguration 通过 SpringFactoriesLoader 加载 META-INF/spring.factories 中的配置类。
  • 条件注解如 @ConditionalOnClass@ConditionalOnMissingBean 控制是否加载。
  • 最终通过 @Bean 方法注册组件到 IOC 容器。

9. Redis 数据类型及用途

  • String:缓存、计数器、分布式锁。
  • Hash:存储对象,如用户信息。
  • List:消息队列、最新列表。
  • Set:去重集合、共同好友。
  • ZSet:排行榜、带权重的消息队列。

10. RabbitMQ 消息不丢失保障

  • 生产者:开启 confirm 模式,异步接收 Broker 确认;配合消息本地数据库+定时补偿。
  • Broker:交换机、队列、消息设置 durable=true 持久化;镜像队列高可用。
  • 消费者:关闭 autoAck,处理成功后手动 channel.basicAck()。

11. DDD 核心概念

  • 领域(Domain):业务核心,划分界限上下文(Bounded Context)。
  • 实体(Entity):有唯一标识的对象,生命周期连续。
  • 值对象(Value Object):无标识,通过属性判断相等,如地址。
  • 聚合(Aggregate):一组相关对象的集合,由聚合根统一管理事务边界。
  • 仓储(Repository):提供聚合的持久化接口,屏蔽底层细节。
  • 工厂(Factory):封装复杂对象创建逻辑。
  • 应用服务 & 领域服务:协调领域对象完成业务逻辑。