ThreadPoolExecutor
ThreadPoolExecutor 是 Java 提供的一个灵活且强大的线程池实现,它位于 java.util.concurrent 包中。通过使用线程池,可以有效管理一组线程,避免频繁创建和销毁线程带来的开销,同时还可以控制并发线程的数量以防止资源耗尽。
核心概念
- 核心线程数(corePoolSize):线程池中保持的最小线程数,即使这些线程处于空闲状态。
- 最大线程数(maximumPoolSize):线程池允许的最大线程数。
- 存活时间(keepAliveTime):当线程数超过核心线程数时,多余的空闲线程在终止前等待新任务的最长时间。
- 时间单位(unit):为 keepAliveTime 指定的时间单位,如秒、分钟等。
- 工作队列(workQueue):用于保存等待执行的任务的阻塞队列。
- 线程工厂(threadFactory):用于创建新线程的工厂,默认情况下使用 Executors.defaultThreadFactory()。
- 拒绝策略(handler):当线程池和队列都满了时,新的任务将被拒绝,并调用这个处理器进行处理。
创建 ThreadPoolExecutor
可以通过构造函数直接创建一个 ThreadPoolExecutor 实例:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize, // 核心线程数
maximumPoolSize, // 最大线程数
keepAliveTime, // 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<Runnable>(), // 工作队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略
常见的使用方式
Java 提供了 Executors 工具类来简化线程池的创建,比如:
- 固定大小线程池:
ExecutorService fixedPool = Executors.newFixedThreadPool(10);
- 缓存线程池:
ExecutorService cachedPool = Executors.newCachedThreadPool();
- 单一线程池:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
执行任务
通过 execute(Runnable command) 方法提交不需要返回值的任务,或者使用 submit(Callable<T> task) 方法提交需要返回结果的任务。
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("Task is running.");
}
});
关闭线程池
有两种方法可以关闭线程池:
- shutdown():平滑地关闭线程池,不再接受新的任务,但会继续执行已提交的任务。
- shutdownNow():尝试立即停止所有正在执行的任务,并返回等待执行的任务列表。
检查线程池是否已经完全关闭可以使用 isTerminated() 方法。
监控与调整
ThreadPoolExecutor 提供了多种方法来监控其状态,例如获取已完成任务数量(getCompletedTaskCount),当前池中的线程数(getPoolSize)等。
拒绝策略
当无法执行更多任务时(即达到了最大线程数并且工作队列已满),可以根据需要选择不同的拒绝策略:
- AbortPolicy:默认策略,抛出 RejectedExecutionException 异常。
- CallerRunsPolicy:由调用线程执行该任务。
- DiscardPolicy:直接丢弃任务,不做任何处理。
- DiscardOldestPolicy:丢弃工作队列中最旧的任务,然后重试执行(可能会再次失败并重试)。
总结
使用 ThreadPoolExecutor 能够有效地管理系统资源,提高程序的稳定性和响应速度。根据具体的应用场景选择合适的配置参数对于优化性能至关重要。