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

46 阅读6分钟

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

面试官:请坐,先简单介绍一下自己。

谢飞机:面试官好,我叫谢飞机,三年Java开发经验,精通CRUD,熟悉Spring全家桶,会用new Thread,哦不,是熟悉多线程编程!

面试官:(微微一笑)那我们开始吧。


第一轮:Java基础与并发编程

面试官:你说你熟悉多线程,那线程和进程的区别是什么?

谢飞机:这个我知道!进程是资源分配的最小单位,线程是CPU调度的最小单位。一个进程可以有多个线程,线程共享进程的内存空间。

面试官:不错,理解到位。那Java中创建线程的方式有哪些?

谢飞机:两种!第一种是继承Thread类,重写run方法;第二种是实现Runnable接口,然后传给Thread构造函数。

面试官:还有呢?

谢飞机:呃……还有Callable + Future?可以有返回值!

面试官:很好。那为什么我们平时推荐使用Runnable而不是继承Thread?

谢飞机:因为Java是单继承啊!我如果继承了Thread,就不能继承别的类了,耦合太高!

面试官:回答得很好。


第二轮:JUC与线程池

面试官:既然提到多线程,那说说什么是线程池?为什么要用线程池?

谢飞机:线程池就是提前创建好一堆线程,放着不用的时候就等着,要用的时候直接拿,避免频繁创建销毁线程带来的开销!还能控制并发数量!

面试官:说得不错。那Java中常见的线程池有哪些?

谢飞机:有FixedThreadPool、CachedThreadPool、SingleThreadExecutor……还有一个叫Scheduled的,可以定时任务!

面试官:那这些线程池底层都是基于哪个类实现的?

谢飞机:嗯……ThreadPool?ThreadPoolExecutor!对!

面试官:很好。那ThreadPoolExecutor的七个核心参数分别是什么?

谢飞机:七个?我记得有核心线程数、最大线程数、空闲时间、时间单位、任务队列……还有两个是啥?(挠头)

面试官:还有一个是线程工厂,另一个是拒绝策略。

谢飞机:对对对!线程工厂用来创建线程,拒绝策略就是任务太多处理不过来时怎么处理,比如抛异常、丢弃、调用者自己执行等等。

面试官:那如果核心线程数是5,最大是10,队列长度是100,现在提交了120个任务,会发生什么?

谢飞机:前5个直接执行,后面95个进队列,第101到120……这时候队列满了,就会创建新的线程,最多到10个,所以还能再处理5个,剩下15个……(支支吾吾)就……就拒绝了?

面试官:基本正确。


第三轮:Spring与分布式技术

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

谢飞机:singleton、prototype,还有request、session、application,但后三个是Web环境下的。

面试官:AOP是怎么实现的?

谢飞机:动态代理!JDK动态代理和CGLIB。JDK基于接口,CGLIB基于子类。

面试官:Redis有哪些数据类型?

谢飞机:String、Hash、List、Set、ZSet!还会用String存JSON!

面试官:缓存穿透怎么解决?

谢飞机:加布隆过滤器!把可能存在的key先记下来,请求进来先查布隆,没有就直接返回,不打数据库!

面试官:Dubbo的负载均衡策略有哪些?

谢飞机:随机、轮询、最少活跃数、一致性哈希……

面试官:xxl-job怎么保证任务不重复执行?

谢飞机:呃……它有个调度中心,应该会锁一下吧……(语无伦次)

面试官:好的,今天先到这里。你的基础还可以,回去等通知吧。

谢飞机:好的好的,谢谢面试官!(心里默念:又一轮面试结束了,不知道能不能过……)


答案详解

1. 线程 vs 进程

  • 进程:操作系统资源分配的基本单位,拥有独立的内存空间。
  • 线程:CPU调度的基本单位,属于某个进程,共享进程的内存和资源。
  • Java中通过ThreadRunnable创建线程。

2. 创建线程的四种方式

  1. 继承Thread
  2. 实现Runnable接口
  3. 实现Callable接口 + FutureTask
  4. 使用线程池(ExecutorService

推荐使用Runnable,避免类单继承限制,也更符合“组合优于继承”原则。

3. 线程池 ThreadPoolExecutor 七大参数

  1. corePoolSize:核心线程数,即使空闲也不会被回收(除非设置allowCoreThreadTimeOut)
  2. maximumPoolSize:最大线程数
  3. keepAliveTime:非核心线程空闲存活时间
  4. unit:时间单位
  5. workQueue:阻塞队列,如ArrayBlockingQueue、LinkedBlockingQueue
  6. threadFactory:线程工厂,用于创建新线程,可自定义命名
  7. handler:拒绝策略,常见有:
    • AbortPolicy(默认,抛异常)
    • CallerRunsPolicy(由调用者线程执行)
    • DiscardPolicy(静默丢弃)
    • DiscardOldestPolicy(丢弃队列最老任务)

4. 提交120个任务的执行流程

  • 前5个任务 → 核心线程执行
  • 接下来95个 → 进入队列(共100容量)
  • 第101~110个 → 创建非核心线程执行(最大10线程)
  • 第111~120个 → 队列满 + 线程数达上限 → 触发拒绝策略

5. Spring Bean作用域

  • singleton:单例(默认)
  • prototype:每次获取都创建新实例
  • request/session/application:Web相关

6. AOP实现原理

  • JDK动态代理:要求目标类实现接口,通过Proxy.newProxyInstance生成代理对象
  • CGLIB:通过继承目标类生成子类,重写方法实现代理,适用于无接口类

7. Redis数据类型

  • String:字符串,适合缓存对象(JSON序列化)
  • Hash:哈希,适合存储对象字段
  • List:列表,适合消息队列
  • Set:集合,去重场景
  • ZSet:有序集合,排行榜场景

8. 缓存穿透

  • 问题:查询不存在的数据,绕过缓存直击数据库
  • 解决方案
    • 布隆过滤器:快速判断key是否存在
    • 缓存空值:对不存在的key也缓存,设置短过期时间

9. Dubbo负载均衡策略

  • RandomLoadBalance:按权重随机(默认)
  • RoundRobinLoadBalance:轮询
  • LeastActiveLoadBalance:最少活跃调用数
  • ConsistentHashLoadBalance:一致性哈希,相同参数请求总到同一节点

10. xxl-job防重复执行

  • 调度中心通过数据库锁(如SELECT FOR UPDATE)保证同一任务在同一时间只被一个调度线程触发
  • 执行器端也有幂等控制,防止网络重试导致重复执行