JUC——Executor 框架与线程池
Executor线程池(Thread Pool)是一种非常重要的并发编程工具,它通过预先创建一定数量的线程并重复使用这些线程来执行任务,从而减少线程的频繁创建和销毁带来的性能开销。Java 提供了强大的线程池支持,主要通过包中的Executor框架来实现。
线程池(Thread Pool)是一种非常重要的并发编程工具,它通过预先创建一定数量的线程并重复使用这些线程来执行任务,从而减少线程的频繁创建和销毁带来的性能开销。Java 提供了强大的线程池支持,主要通过 java.util.concurrent 包中的 Executor 框架来实现。
一、Executor 框架
Java 的 Executor 框架是 Java 并发包(java.util.concurrent)中用于简化多线程编程的一个重要组件。它提供了一种将任务提交与任务执行分离的机制,使开发者可以更专注于业务逻辑,而不必过多关注线程的创建、管理和调度。

Executor 框架主要由以下几个核心接口和类组成:
1. Executor 接口
这是 Executor 框架的最顶层接口,定义了一个非常简单的方法:
void execute(Runnable command);
- 用于提交一个
Runnable类型的任务给线程池或线程执行。 - 它不提供任务的返回值,也不提供对任务执行状态的控制。
2. ExecutorService 接口
ExecutorService 是 Executor 的子接口,扩展了更多功能,提供了对线程池的更全面管理能力。它的主要方法包括:
2.1 提交任务:
void execute(Runnable command);(继承自Executor)<T> Future<T> submit(Callable<T> task);:提交一个有返回值的任务(Callable)。Future<?> submit(Runnable task);:提交一个没有返回值的任务(Runnable)。<T> Future<T> submit(Runnable task, T result);:提交一个Runnable任务,并指定返回结果。
2.2 关闭线程池:
void shutdown();:平缓关闭线程池,不再接受新任务,但会继续执行队列中的任务。List<Runnable> shutdownNow();:立即关闭线程池,尝试停止所有正在执行的任务,并返回等待执行的任务列表。
2.3 其他方法:
boolean isShutdown();:判断线程池是否已关闭。boolean isTerminated();:判断线程池是否已完全终止(所有任务都已完成)。boolean awaitTermination(long timeout, TimeUnit unit):阻塞等待线程池终止,直到超时或线程池完全终止。
ExecutorService是实际开发中最常用的接口,通常通过线程池(如ThreadPoolExecutor)来实现。
3. ThreadPoolExecutor(线程池核心实现)
ThreadPoolExecutor是Executor框架最核心、最灵活的实现,允许高度定制线程池的行为。
核心参数一览表
|
参数 |
类型 |
必填 |
说明 |
推荐配置建议 |
相关影响 |
|---|---|---|---|---|---|
|
corePoolSize |
int |
是 |
线程池中保持的核心线程数量,即使它们处于空闲状态 |
CPU密集型:CPU核心数+1 |
决定线程池的基础并发能力,核心线程默认会一直存活(除非设置allowCoreThreadTimeOut) |
|
maximumPoolSize |
int |
是 |
线程池允许存在的最大线程数量 |
通常为核心线程数的1-2倍(视任务类型而定) |
当工作队列满且线程数小于此值时,会创建新线程执行任务 |
|
keepAliveTime |
long |
是 |
当线程数超过核心线程数时,多余空闲线程的存活时间 |
通常设置为30-60秒 |
控制非核心线程的空闲回收时间,合理设置可平衡资源利用和响应速度 |
|
unit |
TimeUnit |
是 |
keepAliveTime的时间单位 |
TimeUnit.SECONDS(常用) |
配合keepAliveTime使用,定义时间单位 |
|
workQueue |
BlockingQueue<Runnable> |
是 |
用于保存等待执行的任务的阻塞队列 |
CPU密集型:有界队列(如ArrayBlockingQueue) |
决定任务排队策略,直接影响线程创建行为和拒绝策略触发时机 |
|
threadFactory |
ThreadFactory |
否 |
用于创建新线程的工厂 |
建议自定义,为线程设置有意义的名字 |
影响线程的创建方式、名称、优先级等,便于问题排查和监控 |
|
handler |
RejectedExecutionHandler |
否 |
当线程池和工作队列都满时的拒绝策略 |
根据业务需求选择:AbortPolicy(默认)、CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy |
决定系统过载时的处理方式,影响系统的健壮性和可靠性 |
构造函数源码:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
二、线程池
1.线程池的创建方式
1.1. 直接使用ThreadPoolExecutor构造函数(推荐)
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 60;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
1.2. 线程池工作流程
-
提交任务时:
-
如果当前线程数 < corePoolSize,则创建新线程执行任务
-
如果线程数 ≥ corePoolSize,将任务放入工作队列
-
如果队列已满且线程数 < maximumPoolSize,则创建新线程执行任务
-
如果队列已满且线程数 ≥ maximumPoolSize,则执行拒绝策略
-
-
线程执行任务:
-
线程从队列中获取任务并执行
-
执行完成后,线程会尝试从队列中获取下一个任务
-
-
线程空闲处理:
-
核心线程默认会一直存活等待新任务
-
非核心线程(线程数 > corePoolSize)在空闲超过keepAliveTime后会被终止
-
2. 使用Executors工厂方法(不推荐)
Executors工厂类提供的几种常用线程池创建方法:
|
线程池类型 |
创建方法 |
特点 |
潜在问题 |
|---|---|---|---|
|
固定大小线程池 |
|
线程数量固定,线程空闲也不会被回收 |
队列无界,可能导致OOM(内存溢出),任务可能长时间等待 |
|
单线程线程池 |
|
只有一个工作线程,保证任务按顺序执行(FIFO) |
队列无界,可能导致OOM,单线程故障会导致任务阻塞 |
|
可缓存线程池 |
|
线程数量根据需求自动调整,空闲线程60秒后回收 |
线程数可能无限增长(达到Integer.MAX_VALUE),可能导致资源耗尽 |
|
定时任务线程池 |
|
支持定时及周期性任务执行 |
最大线程数理论上无限制,长期运行可能积累大量任务 |
|
单线程定时任务池 |
|
单线程执行定时任务,保证任务顺序执行 |
单线程故障会影响后续任务,无界队列可能积累大量任务 |
3.注意
《阿里巴巴开发手册》强制要求线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
更多推荐




所有评论(0)