面试官:Java线程池的核心参数了解吗?谢飞机:会用new Thread就不错了!
面试官:请坐,先简单介绍一下自己。
谢飞机:面试官好,我叫谢飞机,三年Java开发经验,精通SSH、SSM,会用Spring Boot,能写SQL,会敲Linux命令,会画圈(UML)……
面试官:咳咳,我们开始吧。
第一轮:基础热身 —— Java 核心与集合类
面试官:ArrayList 和 LinkedList 的区别是什么?
谢飞机:这个我知道!ArrayList 是基于数组的,查询快,增删慢;LinkedList 是基于链表的,增删快,查询慢!
面试官:不错,理解到位。
谢飞机:那必须的,我还知道 ArrayList 默认初始容量是10,扩容是1.5倍!
面试官:很好。那 HashMap 的底层结构呢?
谢飞机:嗯……是数组加链表,JDK8之后链表长度超过8变成红黑树!
面试官:那如果两个 key 的 hash 值一样,怎么处理?
谢飞机:放在同一个桶里,形成链表或者红黑树,通过 equals 比较 key!
面试官:回答得很好,继续。
第二轮:进阶挑战 —— 多线程与线程池
面试官:说说你对线程池的理解,ThreadPoolExecutor 的核心参数有哪些?
谢飞机:核心参数?有 corePoolSize、maximumPoolSize……还有 keepAliveTime,队列……好像是 BlockingQueue……
面试官:那 workQueue 有哪些常见实现?
谢飞机:ArrayBlockingQueue、LinkedBlockingQueue……PriorityBlockingQueue!我项目里都用过!
面试官:那你项目中用的是哪种?为什么?
谢飞机:我……一般用 Executors.newFixedThreadPool(),方便!
面试官:……(皱眉)那你了解它背后的 LinkedBlockingQueue 容量是多少吗?
谢飞机:啊?默认……无限大?好像是 Integer.MAX_VALUE……哦不对,应该是 1024?
面试官:它是无界的,容易导致 OOM。为什么不推荐使用 Executors 创建线程池?
谢飞机:因为……规范不让用?阿里手册写了……
面试官:(点头)算是答到了点上。
第三轮:综合实战 —— Spring 与分布式组件
面试官:Spring 中 Bean 的作用域有哪些?
谢飞机:singleton、prototype,还有 request、session……我用得最多是 singleton!
面试官:Bean 的生命周期了解吗?
谢飞机:实例化、填充属性、初始化……销毁!中间还能加后置处理器!
面试官:不错。那你说说 Redis 的持久化机制?
谢飞机:RDB 是快照,AOF 是日志追加,可以同时开!
面试官:那如果 Redis 宕机,哪个数据更完整?
谢飞机:当然是 AOF!它每秒同步一次,比 RDB 准!
面试官:如果开启 appendfsync always 呢?
谢飞机:那……每次写都同步,最安全!就是慢一点……
面试官:很好。最后一个问题:Dubbo 的负载均衡策略有哪些?
谢飞机:随机、轮询、最少活跃调用数……还有……一致性哈希!
面试官:如果某个服务节点响应特别慢,Dubbo 怎么感知并剔除?
谢飞机:呃……超时了就重试别的?监控?心跳?我配过超时时间,但没深入看过……
面试官:(微笑)今天就到这里,你的基础知识还不错,有些细节还需要加强。回去等通知吧。
谢飞机:好的好的,谢谢面试官!我回去就把 Executors 全换成 ThreadPoolExecutor!
参考答案详解
1. ArrayList vs LinkedList
- ArrayList:基于动态数组,支持随机访问(O(1)),扩容机制为
oldCapacity + (oldCapacity >> 1),即1.5倍。 - LinkedList:双向链表,插入删除快(O(1)),但遍历慢(O(n)),且占用更多内存(前后指针)。
使用场景:频繁查询用 ArrayList,频繁增删用 LinkedList。
2. HashMap 底层原理
- JDK8 之前:数组 + 链表
- JDK8 之后:数组 + 链表 + 红黑树(当链表长度 ≥ 8 且数组长度 ≥ 64 时转换)
- Hash 冲突:通过拉链法解决,equals 判断 key 是否相同。
- 扩容:loadFactor 默认 0.75,达到阈值后扩容为原大小2倍,并 rehash。
3. ThreadPoolExecutor 核心参数
corePoolSize:核心线程数,即使空闲也不会回收(除非设置 allowCoreThreadTimeOut)maximumPoolSize:最大线程数keepAliveTime:非核心线程空闲存活时间unit:时间单位workQueue:任务队列,常用:ArrayBlockingQueue:有界队列LinkedBlockingQueue:无界队列(Executors.newFixedThreadPool 使用,默认容量 Integer.MAX_VALUE)SynchronousQueue:不存储元素,每个插入必须等待取出(newCachedThreadPool 使用)PriorityBlockingQueue:优先级队列
threadFactory:线程创建工厂handler:拒绝策略(AbortPolicy、CallerRunsPolicy 等)
为什么不推荐 Executors?
newFixedThreadPool使用无界队列,可能导致大量任务堆积,OOM。newSingleThreadExecutor同理。newCachedThreadPool最大线程数为 Integer.MAX_VALUE,可能创建过多线程,系统崩溃。
4. Spring Bean 作用域
singleton:容器唯一实例(默认)prototype:每次获取都新建实例request:每个 HTTP 请求一个实例(Web 环境)session:每个 HTTP session 一个实例application:每个 ServletContext 一个实例
5. Redis 持久化
- RDB:定时快照,恢复快,数据可能丢失(最后一次快照后数据)
- AOF:记录所有写命令,数据更完整,文件大,恢复慢
appendfsync always:每次写操作都同步到磁盘,最安全,性能最差- 推荐:RDB + AOF 混合使用(Redis 4.0+)
6. Dubbo 负载均衡
RandomLoadBalance:按权重随机(默认)RoundRobinLoadBalance:轮询LeastActiveLoadBalance:最少活跃调用数(避免慢节点积压)ConsistentHashLoadBalance:一致性哈希,相同参数请求同节点
节点健康检测:通过心跳机制(默认 2s 一次),失败一定次数后从注册中心剔除。