面试官:讲讲Java中线程池的核心参数和工作流程?谢飞机:这题我会!
面试官:你好,谢飞机,请坐。我看到你简历上写了熟悉Java并发编程,那我们来聊聊线程池吧。
谢飞机:(挺起胸膛)哎哟,这个我熟!ThreadPoolExecutor,我天天用!
面试官:好,那你说说,Java中线程池的核心参数有哪些?
谢飞机:嗯……有核心线程数、最大线程数、一个队列,还有……还有个线程工厂!对,就这四个!
面试官:不错,基本答出来了。那这四个参数分别起什么作用?
谢飞机:核心线程数嘛,就是最少要开几个线程干活;最大线程数就是最多不能超过多少个线程;队列就是任务太多的时候先放那儿排队;线程工厂就是用来创建新线程的——比如可以给线程起名字,方便排查问题!
面试官:很好,那如果任务提交进来,线程池是怎么处理的?
谢飞机:这个更简单了!首先看有没有空闲线程,没有的话就新建线程直到达到核心线程数;然后任务就进队列;队列满了,就继续开线程直到最大线程数;再满了……哦,那就拒绝呗,抛异常!
面试官:嗯,说得不错。那你再说说常见的阻塞队列有哪些?
谢飞机:ArrayBlockingQueue、LinkedBlockingQueue……还有……PriorityBlockingQueue!对,优先级队列!
面试官:可以。那如果使用的是无界队列,比如 LinkedBlockingQueue,默认容量是多少?会有什么风险?
谢飞机:默认……应该是 Integer.MAX_VALUE 吧?风险嘛……内存爆了?(挠头)好像听说过 OOM……
面试官:对,有可能导致内存溢出。那你平时项目里怎么配置线程池的?
谢飞机:呃……我们用 @Async 注解,好像也没配啥……默认的吧……
面试官:(微笑)建议你在实际项目中还是要根据业务场景合理设置参数,避免资源耗尽。
谢飞机:明白明白,回家就改!
面试官:今天先到这里,你的基础还行,回去等通知吧。
【答案详解】:Java线程池核心参数与工作流程
一、ThreadPoolExecutor 的七大构造参数
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit,
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
- corePoolSize:核心线程数,即使空闲也不会被回收(除非设置 allowCoreThreadTimeOut)。
- maximumPoolSize:最大线程数,线程池允许创建的最大线程数量。
- keepAliveTime + unit:非核心线程空闲时的存活时间,超时后会被销毁。
- workQueue:用于存放等待执行的任务的阻塞队列。
ArrayBlockingQueue:有界队列,需指定大小。LinkedBlockingQueue:通常为无界(默认 Integer.MAX_VALUE),可能导致 OOM。SynchronousQueue:不存储元素,每个插入必须等待另一个线程取出。DelayQueue:延迟执行任务。
- threadFactory:自定义线程创建方式,推荐命名以便调试。
- handler:当队列满且线程数达上限时的拒绝策略。
AbortPolicy(默认):抛出 RejectedExecutionException。CallerRunsPolicy:由提交任务的线程自己执行。DiscardPolicy:静默丢弃任务。DiscardOldestPolicy:丢弃队列中最老的任务,重试提交当前任务。
二、任务提交流程(执行顺序)
- 当提交一个新任务时:
- 若当前运行线程数 < corePoolSize,则创建新线程执行任务(即使有空闲线程)。
- 否则,尝试将任务加入 workQueue。
- 若 workQueue 已满,且当前线程数 < maximumPoolSize,则创建非核心线程执行任务。
- 若线程数已达 maximumPoolSize 且队列已满,则触发拒绝策略。
三、最佳实践建议
- 避免使用 Executors 工具类创建线程池(如 newFixedThreadPool 使用无界队列,易导致 OOM)。
- 应显式使用 ThreadPoolExecutor 构造函数,明确参数含义。
- 根据业务类型选择合适的队列和线程数:
- CPU 密集型:线程数 ≈ CPU 核数。
- IO 密集型:线程数可适当增大。
- 为线程池命名,便于日志追踪。
- 监控线程池状态:活跃线程数、队列大小、已完成任务数等。
小贴士:Spring 中可通过
@EnableAsync+ 自定义TaskExecutor实现可控的异步线程池管理。