在 Java 高并发编程中,线程池是绕不开的核心技术,也是面试必问的重点模块。它解决了频繁创建 / 销毁线程带来的性能损耗,实现了线程复用、任务管理、并发控制等核心能力。
一、线程池整体架构:Executor 体系
Java 线程池基于 Executor 框架实现,核心类关系如下:
- Executor :顶层接口,只有一个
execute()方法,功能过于简单。 - ExecutorService:继承 Executor,扩展了 submit、shutdown、invokeAll 等能力,是实际开发中最常用的接口。
- ThreadPoolExecutor:线程池真正的实现类,所有线程池最终都通过它创建。
- Executors:工具类,提供快速创建线程池的静态方法。

execute 和 submit 的区别(高频面试题)
-
归属不同
execute()是顶层接口Executor的方法。submit()是ExecutorService的方法。
-
参数与返回值
execute()只支持Runnable,无返回值。submit()支持Runnable/Callable,返回Future对象,可获取结果、取消任务、判断执行状态。
-
异常处理
execute()提交的任务异常无法直接捕获,会直接抛出。submit()可通过Future.get()捕获任务内部异常。
二、Executors 工具类:快速创建线程池
JDK 提供 Executors 工具类,可以快速创建几种常用线程池:
1. 普通线程池示例
public class ExecutorsDemo {
public static void main(String[] args) throws Exception {
// 创建单线程线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// submit 提交带返回值的任务
Future<String> future = executorService.submit(() -> {
System.out.println(Thread.currentThread().getName() + " 任务执行中...");
return "线程任务执行完成";
});
// 获取返回结果
String result = future.get();
System.out.println("主线程获取结果:" + result);
executorService.shutdown();
}
}
2. 定时任务线程池(延迟执行)
public class ScheduledThreadPoolDemo {
public static void main(String[] args) {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
System.out.println("当前时间:" + new Date());
// 延迟 5 秒执行
pool.schedule(() -> {
System.out.println(Thread.currentThread().getName() + " 延迟任务执行 " + new Date());
}, 5, TimeUnit.SECONDS);
pool.shutdown();
}
}
3. 定时任务:延迟 + 固定周期执行
public class ScheduledAtFixRateDemo {
public static void main(String[] args) {
ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
// 初始延迟5秒,之后每隔1秒执行一次
pool.scheduleAtFixedRate(() -> {
System.out.println(Thread.currentThread().getName() + " 周期任务执行 " + new Date());
}, 5, 1, TimeUnit.SECONDS);
}
}
注意:周期执行任务不能调用 shutdown,否则线程池关闭,任务无法继续。
三、线程池底层核心:7 大参数(必须背会)
ThreadPoolExecutor 的构造方法是线程池的灵魂,包含 7 个核心参数:
ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)

参数说明
-
corePoolSize常驻核心线程数,即使空闲也不会被销毁(默认)。
-
maximumPoolSize 线程池能容纳的最大线程总数,必须 ≥1。
-
keepAliveTime + unit当线程数 > corePoolSize 时,多余空闲线程的存活时间,超时会被回收。
-
workQueue 任务队列,用于存放提交但未执行的任务。常用:
ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue。 -
threadFactory创建线程的工厂,默认即可,也可自定义线程名、优先级。
-
handler拒绝策略:队列满 + 线程数达到 maximumPoolSize 时触发。
四、线程池工作流程(底层原理)
提交任务后,线程池执行流程如下:
- 刚创建线程池时,线程数为 0。
- 任务提交:
- 运行线程 < corePoolSize:立即创建核心线程执行任务。
- 运行线程 ≥ corePoolSize:任务进入队列等待。
- 队列满了,但运行线程 < maximumPoolSize:创建非核心线程执行任务。
- 队列满 + 运行线程 = maximumPoolSize:触发拒绝策略。
- 线程执行完任务后,会从队列复用线程取任务执行。
- 非核心线程空闲超过 keepAliveTime,会被销毁,最终线程数收缩回 corePoolSize。
一句话总结:先核心线程 → 再队列 → 再非核心线程 → 最后拒绝策略。

五、4 种内置拒绝策略
JDK 提供 4 种实现 RejectedExecutionHandler 的拒绝策略:
-
AbortPolicy(默认) 直接抛出
RejectedExecutionException,阻止系统继续运行。 -
CallerRunsPolicy 任务回退到调用者线程执行,不抛异常、不丢弃,降低提交速度。
-
DiscardOldestPolicy 丢弃队列中等待最久的任务,再尝试加入当前任务。
-
DiscardPolicy 静默丢弃任务,不抛异常、不处理,允许任务丢失时使用。
也可以自定义拒绝策略 ,实现 RejectedExecutionHandler 接口即可。
六、重点:为什么阿里规范禁止用 Executors?
《阿里巴巴 Java 开发手册》明确规定:
线程池不允许使用 Executors 创建,必须通过 ThreadPoolExecutor 自定义。
原因:
Executors.newFixedThreadPool/newSingleThreadExecutor队列是LinkedBlockingQueue,容量为Integer.MAX_VALUE,会导致大量任务堆积,OOM 内存溢出。Executors.newCachedThreadPool最大线程数是Integer.MAX_VALUE,可能创建大量线程,导致 OOM。
结论:生产环境必须自定义线程池,明确核心线程、最大线程、队列容量、拒绝策略。
七、自定义线程池(企业级标准写法)
class MyTask implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 执行业务");
}
}
public class CustomThreadPoolDemo {
public static void main(String[] args) {
// 自定义线程池
ExecutorService pool = new ThreadPoolExecutor(
2, // corePoolSize
5, // maximumPoolSize
2, // keepAliveTime
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3), // 有界队列
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy() // 默认拒绝策略
);
try {
// 模拟提交 9 个任务
for (int i = 0; i < 9; i++) {
pool.execute(new MyTask());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
pool.shutdown();
}
}
}
任务提交流程:
- 前 2 个:核心线程执行
- 接下来 3 个:进入队列
- 再接下来 3 个:创建非核心线程(总线程达到 5)
- 第 9 个任务:队列满 + 线程满 → 触发拒绝策略,抛出异常
八、线程池的核心优势总结
-
线程复用避免频繁创建 / 销毁线程,大幅降低系统开销。
-
控制并发度通过队列和最大线程数,防止无限创建线程导致系统崩溃。
-
统一管理线程生命周期自动创建、回收、超时处理,减少资源泄漏。
-
提高响应速度任务到达时直接使用已有线程,无需等待线程创建。
-
规范安全自定义线程池可避免 OOM,符合企业开发规范。
