Java线程池ThreadPoolExecutor详解:从使用到源码深度剖析
·
一、为什么要使用线程池?
在深入ThreadPoolExecutor之前,我们先明确使用线程池的必要性:
- 降低资源消耗:通过重复利用已创建的线程,降低线程创建和销毁造成的消耗
- 提高响应速度:当任务到达时,任务可以不需要等待线程创建就能立即执行
- 提高线程可管理性:线程是稀缺资源,使用线程池可以进行统一分配、调优和监控
- 提供更强大的功能:线程池具备可扩展性,允许开发人员向其中增加更多的功能
二、ThreadPoolExecutor类结构概览
public class ThreadPoolExecutor extends AbstractExecutorService {
// 核心字段
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private final BlockingQueue<Runnable> workQueue;
private final HashSet<Worker> workers = new HashSet<Worker>();
private volatile ThreadFactory threadFactory;
private volatile RejectedExecutionHandler handler;
private volatile long keepAliveTime;
private volatile int corePoolSize;
private volatile int maximumPoolSize;
// 主要构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 参数校验和初始化
}
}
三、七大核心参数深度解析
3.1 corePoolSize - 核心线程数
作用:线程池中保持存活的最小线程数量,即使这些线程处于空闲状态。
工作机制:
- 当提交新任务时,如果当前线程数 < corePoolSize,即使存在空闲线程,也会创建新线程
- 默认情况下,核心线程会一直存活,除非设置allowCoreThreadTimeOut
public class CorePoolSizeExample {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize - 核心线程数
5, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10)
);
// 提交任务
for (int i = 0; i < 3; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " executed by " +
Thread.currentThread().getName());
});
}
// 输出线程池状态
System.out.println("核心线程数: " + executor.getCorePoolSize());
System.out.println("当前线程数: " + executor.getPoolSize());
executor.shutdown();
}
}
配置建议:
- CPU密集型任务:CPU核心数 + 1
- IO密集型任务:CPU核心数 × 2
- 混合型任务:(CPU核心数 × IO等待时间) / CPU计算时间
3.2 maximumPoolSize - 最大线程数
作用:线程池允许创建的最大线程数量。
工作机制:
- 当workQueue已满且当前线程数 < maximumPoolSize时,会创建新线程
- 达到maximumPoolSize后,新任务会触发拒绝策略
public class MaximumPoolSizeExample {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize - 最大线程数
1, // keepAliveTime
TimeUnit.SECONDS,
new SynchronousQueue<>() // 无缓冲队列
);
// 提交6个任务,观察线程创建情况
for (int i = 0; i < 6; i++) {
final int taskId = i;
try {
executor.execute(() -> {
try {
Thread.sleep(1000);
System.out.println("Task " + taskId + " completed by " +
Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
System.out.println("Task " + taskId + " submitted");
} catch (RejectedExecutionException e) {
System.out.println("Task " + taskId + " rejected");
}
}
Thread.sleep(3000);
System.out.println("最终线程数: " + executor.getPoolSize());
executor.shutdown();
}
}
3.3 keepAliveTime - 线程存活时间
作用:当线程数大于核心线程数时,多余的空闲线程在终止前等待新任务的最长时间。
工作机制:
- 仅对超出corePoolSize的线程有效
- 配合TimeUnit单位使用
- 设置allowCoreThreadTimeOut为true时,核心线程也会超时终止
public class KeepAliveTimeExample {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
2, // keepAliveTime - 线程存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2)
);
// 允许核心线程超时
executor.allowCoreThreadTimeOut(true);
System.out.println("初始线程数: " + executor.getPoolSize());
// 提交一批任务
for (int i = 0; i < 6; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println("Task " + taskId + " started by " +
Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
Thread.sleep(1000);
System.out.println("任务执行后线程数: " + executor.getPoolSize());
Thread.sleep(3000); // 等待超时
System.out.println("超时后线程数: " + executor.getPoolSize());
executor.shutdown();
}
}
3.4 TimeUnit - 时间单位
作用:keepAliveTime参数的时间单位。
常用单位:
- TimeUnit.NANOSECONDS:纳秒
- TimeUnit.MICROSECONDS:微秒
- TimeUnit.MILLISECONDS:毫秒
- TimeUnit.SECONDS:秒
- TimeUnit.MINUTES:分钟
- TimeUnit.HOURS:小时
- TimeUnit.DAYS:天
3.5 workQueue - 工作队列
作用:用于保存等待执行的任务的阻塞队列。
常用队列类型及适用场景:
3.5.1 SynchronousQueue - 直接传递队列
public class SynchronousQueueExample {
public static void main(String[] args) {
// SynchronousQueue:不存储元素,每个插入操作必须等待另一个线程的移除操作
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new SynchronousQueue<>()
);
// 适用于任务处理速度快的场景,能够快速创建新线程
}
}
3.5.2 LinkedBlockingQueue - 无界队列
public class LinkedBlockingQueueExample {
public static void main(String[] args) {
// LinkedBlockingQueue:基于链表的无界队列(默认Integer.MAX_VALUE)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>() // 无界队列,maximumPoolSize无效
);
// 适用于任务量不可预测但需要平滑处理的场景
}
}
3.5.3 ArrayBlockingQueue - 有界队列
public class ArrayBlockingQueueExample {
public static void main(String[] args) {
// ArrayBlockingQueue:基于数组的有界队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10) // 有界队列,容量10
);
// 适用于需要控制资源使用的场景
}
}
3.5.4 PriorityBlockingQueue - 优先级队列
public class PriorityBlockingQueueExample {
static class PriorityTask implements Runnable, Comparable<PriorityTask> {
private int priority;
private String name;
public PriorityTask(String name, int priority) {
this.name = name;
this.priority = priority;
}
@Override
public void run() {
System.out.println("Executing: " + name + " with priority: " + priority);
}
@Override
public int compareTo(PriorityTask other) {
return Integer.compare(other.priority, this.priority); // 降序
}
}
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new PriorityBlockingQueue<>()
);
// 提交不同优先级的任务
executor.execute(new PriorityTask("High", 10));
executor.execute(new PriorityTask("Low", 1));
executor.execute(new PriorityTask("Medium", 5));
executor.shutdown();
}
}
3.6 ThreadFactory - 线程工厂
作用:用于创建新线程,可以定制线程的属性。
public class CustomThreadFactoryExample {
static class CustomThreadFactory implements ThreadFactory {
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
private final ThreadGroup group;
public CustomThreadFactory(String poolName) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = poolName + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
// 设置线程属性
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
// 设置异常处理器
t.setUncaughtExceptionHandler((thread, throwable) -> {
System.err.println("Uncaught exception in thread: " + thread.getName());
throwable.printStackTrace();
});
return t;
}
}
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10),
new CustomThreadFactory("CustomPool") // 自定义线程工厂
);
executor.execute(() -> System.out.println(
"Task executed by: " + Thread.currentThread().getName()));
executor.shutdown();
}
}
3.7 RejectedExecutionHandler - 拒绝策略
作用:当线程池和队列都已满时,处理新提交的任务。
3.7.1 内置拒绝策略
public class RejectionPolicyExample {
public static void main(String[] args) {
// 1. AbortPolicy - 默认策略,抛出RejectedExecutionException
testRejectionPolicy(new ThreadPoolExecutor.AbortPolicy(), "AbortPolicy");
// 2. CallerRunsPolicy - 由调用者线程执行任务
testRejectionPolicy(new ThreadPoolExecutor.CallerRunsPolicy(), "CallerRunsPolicy");
// 3. DiscardPolicy - 静默丢弃任务
testRejectionPolicy(new ThreadPoolExecutor.DiscardPolicy(), "DiscardPolicy");
// 4. DiscardOldestPolicy - 丢弃队列中最老的任务
testRejectionPolicy(new ThreadPoolExecutor.DiscardOldestPolicy(), "DiscardOldestPolicy");
}
static void testRejectionPolicy(RejectedExecutionHandler handler, String policyName) {
System.out.println("\n=== Testing " + policyName + " ===");
ThreadPoolExecutor executor = new ThreadPoolExecutor(
1, 1, 0, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1),
handler
);
try {
// 提交3个任务到容量为2的线程池(1个执行 + 1个队列)
for (int i = 0; i < 3; i++) {
final int taskId = i;
try {
executor.execute(() -> {
try {
Thread.sleep(1000);
System.out.println("Task " + taskId + " completed");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
System.out.println("Task " + taskId + " submitted successfully");
} catch (RejectedExecutionException e) {
System.out.println("Task " + taskId + " rejected: " + e.getMessage());
}
}
} finally {
executor.shutdown();
}
}
}
3.7.2 自定义拒绝策略
public class CustomRejectionPolicy {
static class LoggingRejectionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 记录日志
System.err.println("Task rejected: " + r.toString());
System.err.println("Executor state: " + executor.toString());
// 可选的降级策略
if (!executor.isShutdown()) {
System.out.println("Executing in caller thread as fallback");
r.run(); // 在调用者线程中执行
}
}
}
static class RetryRejectionHandler implements RejectedExecutionHandler {
private final int maxRetries;
private final long retryDelayMs;
public RetryRejectionHandler(int maxRetries, long retryDelayMs) {
this.maxRetries = maxRetries;
this.retryDelayMs = retryDelayMs;
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
for (int retry = 0; retry < maxRetries; retry++) {
try {
if (executor.getQueue().offer(r, retryDelayMs, TimeUnit.MILLISECONDS)) {
System.out.println("Task requeued after " + retry + " retries");
return;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
// 最终失败处理
System.err.println("Task failed after " + maxRetries + " retries");
}
}
}
四、ThreadPoolExecutor执行流程深度剖析
4.1 核心执行流程
// 简化版的执行流程(实际源码在ThreadPoolExecutor.execute方法)
public void execute(Runnable command) {
if (command == null) throw new NullPointerException();
int c = ctl.get();
// 阶段1:当前线程数 < corePoolSize
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) // 创建核心线程
return;
c = ctl.get();
}
// 阶段2:线程池运行中且任务可以入队
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command); // 线程池已关闭,拒绝任务
else if (workerCountOf(recheck) == 0)
addWorker(null, false); // 创建非核心线程
}
// 阶段3:队列已满,尝试创建非核心线程
else if (!addWorker(command, false))
reject(command); // 线程池已满,执行拒绝策略
}
4.2 完整执行流程图
五、四种常用线程池的底层实现
5.1 通过Executors工具类创建
public class ExecutorsAnalysis {
public static void main(String[] args) {
// 1. FixedThreadPool - 固定线程数
ExecutorService fixedPool = Executors.newFixedThreadPool(5);
// 底层:new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>())
// 2. CachedThreadPool - 可缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();
// 底层:new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
// new SynchronousQueue<Runnable>())
// 3. SingleThreadExecutor - 单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();
// 底层:new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
// new LinkedBlockingQueue<Runnable>())
// 4. ScheduledThreadPool - 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
// 底层:new ScheduledThreadPoolExecutor(corePoolSize)
}
}
六、线程池监控与调优实战
6.1 线程池状态监控
public class ThreadPoolMonitor {
private final ThreadPoolExecutor executor;
private final ScheduledExecutorService monitor;
public ThreadPoolMonitor(ThreadPoolExecutor executor) {
this.executor = executor;
this.monitor = Executors.newSingleThreadScheduledExecutor();
}
public void startMonitoring() {
monitor.scheduleAtFixedRate(this::collectMetrics, 0, 1, TimeUnit.SECONDS);
}
private void collectMetrics() {
// 基础指标
int poolSize = executor.getPoolSize();
int activeCount = executor.getActiveCount();
long completedTaskCount = executor.getCompletedTaskCount();
long taskCount = executor.getTaskCount();
int queueSize = executor.getQueue().size();
// 计算饱和度
double saturation = (double) activeCount / executor.getMaximumPoolSize();
System.out.printf(
"Pool: %d/%d, Active: %d, Queue: %d, Completed: %d, Saturation: %.2f%n",
poolSize, executor.getMaximumPoolSize(), activeCount,
queueSize, completedTaskCount, saturation
);
// 预警机制
if (saturation > 0.8) {
System.err.println("WARNING: Thread pool saturation high: " + saturation);
}
}
public void stopMonitoring() {
monitor.shutdown();
}
// 动态调整线程池参数
public void dynamicAdjust(int newCoreSize, int newMaxSize) {
executor.setCorePoolSize(newCoreSize);
executor.setMaximumPoolSize(newMaxSize);
System.out.println("Thread pool adjusted: core=" + newCoreSize + ", max=" + newMaxSize);
}
}
6.2 使用示例
public class ThreadPoolBestPractice {
public static void main(String[] args) throws Exception {
// 创建可监控的线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
10, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new CustomThreadFactory("BusinessPool"),
new LoggingRejectionHandler()
);
// 启动监控
ThreadPoolMonitor monitor = new ThreadPoolMonitor(executor);
monitor.startMonitoring();
// 模拟任务提交
for (int i = 0; i < 200; i++) {
final int taskId = i;
executor.execute(() -> {
try {
// 模拟业务处理
Thread.sleep(100 + (int)(Math.random() * 400));
System.out.println("Processed task: " + taskId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 控制提交速度
if (i % 50 == 0) {
Thread.sleep(1000);
}
}
// 动态调整(基于监控数据)
Thread.sleep(5000);
monitor.dynamicAdjust(5, 15);
// 优雅关闭
executor.shutdown();
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
monitor.stopMonitoring();
}
}
七、常见问题与解决方案
7.1 线程池配置最佳实践
public class ThreadPoolConfigGuide {
/**
* 根据业务类型推荐线程池配置
*/
public static ThreadPoolExecutor createOptimalPool(WorkloadType type) {
int cpuCores = Runtime.getRuntime().availableProcessors();
switch (type) {
case CPU_INTENSIVE:
// CPU密集型:线程数不宜过多,避免频繁上下文切换
return new ThreadPoolExecutor(
cpuCores, cpuCores + 1, 30L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000)
);
case IO_INTENSIVE:
// IO密集型:可以配置更多线程
return new ThreadPoolExecutor(
cpuCores * 2, cpuCores * 4, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2000)
);
case MIXED:
// 混合型:适中配置
return new ThreadPoolExecutor(
cpuCores, cpuCores * 2, 45L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(500)
);
default:
throw new IllegalArgumentException("Unknown workload type");
}
}
enum WorkloadType {
CPU_INTENSIVE, // 计算密集:加密、算法等
IO_INTENSIVE, // IO密集:网络请求、数据库操作
MIXED // 混合型
}
}
7.2 避免的坑
-
无界队列导致内存溢出
// 错误示例 new ThreadPoolExecutor(n, n, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); // 可能导致OOM // 正确做法 new ThreadPoolExecutor(n, n, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1000)); // 设置合理边界 -
不合理的线程超时设置
// 错误:核心线程频繁创建销毁 executor.allowCoreThreadTimeOut(true); executor.setKeepAliveTime(1, TimeUnit.SECONDS); // 正确:根据业务特点设置合理超时 executor.setKeepAliveTime(60, TimeUnit.SECONDS); // 适度超时
八、总结
ThreadPoolExecutor是Java并发编程的核心组件,合理使用需要深入理解其七大参数:
- corePoolSize:根据任务类型合理设置,避免过度创建或资源浪费
- maximumPoolSize:设置合理的上限,防止资源耗尽
- keepAliveTime:平衡资源利用和响应速度
- workQueue:根据任务特点和系统负载选择合适的队列
- ThreadFactory:定制线程创建,便于监控和问题排查
- RejectedExecutionHandler:提供合适的降级策略
最佳实践建议:
- 监控线程池运行状态,动态调整参数
- 为不同业务场景创建独立的线程池
- 设置合理的队列边界和拒绝策略
- 在Spring等框架中合理配置线程池
通过深入理解ThreadPoolExecutor的工作原理和合理配置,可以构建出高性能、高可用的并发处理系统。
更多推荐

所有评论(0)