外观
ThreadPollExecutor 是什么?
⭐ 题目日期:
京东 - 2024/12/26
📝 题解:
ThreadPoolExecutor
是 Java 中用于管理线程池的核心类(位于 java.util.concurrent
包),它提供了一种高效、灵活的机制来执行异步任务。通过复用线程、控制并发数量及管理任务队列,它能显著提升多线程程序的性能和稳定性。
核心作用
- 线程复用:避免频繁创建和销毁线程的开销。
- 资源管理:限制并发线程数,防止系统过载。
- 任务调度:按策略处理任务提交、排队、执行和拒绝。
关键参数
创建 ThreadPoolExecutor
需配置以下参数:
核心线程数(corePoolSize)
- 线程池长期保留的线程数量,即使空闲也不会销毁(除非设置
allowCoreThreadTimeOut
)。
- 线程池长期保留的线程数量,即使空闲也不会销毁(除非设置
最大线程数(maximumPoolSize)
- 线程池允许创建的最大线程数。当任务队列满时,会创建新线程直到达到此值。
任务队列(workQueue)
- 用于缓存未执行的任务。常见类型:
LinkedBlockingQueue
(无界队列,可能导致内存溢出)ArrayBlockingQueue
(有界队列)SynchronousQueue
(直接传递任务,不缓存)
- 用于缓存未执行的任务。常见类型:
线程存活时间(keepAliveTime)
- 非核心线程空闲时的存活时间,超时后自动销毁。
拒绝策略(RejectedExecutionHandler)
- 当线程池和队列已满时,处理新任务的策略。常见策略:
- AbortPolicy(默认):抛出
RejectedExecutionException
。 - CallerRunsPolicy:由提交任务的线程直接执行。
- DiscardPolicy:静默丢弃任务。
- DiscardOldestPolicy:丢弃队列中最旧的任务,重新提交新任务。
- AbortPolicy(默认):抛出
- 当线程池和队列已满时,处理新任务的策略。常见策略:
工作流程
- 提交任务时,若当前线程数 < 核心线程数,直接创建新线程执行。
- 若线程数 ≥ 核心数,任务进入队列等待。
- 若队列已满且线程数 < 最大线程数,创建新线程执行任务。
- 若队列和线程数均满,触发拒绝策略。
使用示例
import java.util.concurrent.*;
public class Example {
public static void main(String[] args) {
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数
4, // 最大线程数
60, // 空闲线程存活时间(秒)
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10), // 容量为10的任务队列
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务
for (int i = 0; i < 15; i++) {
executor.execute(() -> {
System.out.println("任务执行线程: " + Thread.currentThread().getName());
});
}
// 关闭线程池
executor.shutdown();
}
}
常见线程池工具
Java 的 Executors
工具类提供了一些预配置的线程池(底层基于 ThreadPoolExecutor
):
- newFixedThreadPool:固定线程数,使用无界队列。
- newCachedThreadPool:线程数可无限扩展,适合短时任务。
- newSingleThreadExecutor:单线程串行执行任务。
- newScheduledThreadPool:支持定时或周期性任务。
注意事项
- 避免无界队列:可能导致内存溢出(如
LinkedBlockingQueue
未指定容量)。 - 合理设置线程数:根据任务类型(CPU密集型、IO密集型)调整。
- 正确关闭线程池:使用
shutdown()
平滑关闭,或shutdownNow()
强制中断。
通过合理配置 ThreadPoolExecutor
,可以有效平衡系统资源与任务吞吐量,是多线程编程中的关键组件。