Java 线程池是一种管理并发线程的机制,通过复用线程减少创建和销毁线程的开销,从而提高应用程序的性能。线程池的主要原理包括以下几个方面:
1. 线程池的基本结构
- 线程池(ThreadPoolExecutor) 是
java.util.concurrent包中的核心类。它主要由以下几个部分组成:- 任务队列(BlockingQueue workQueue): 保存等待执行的任务。常见的队列类型有
LinkedBlockingQueue、SynchronousQueue、ArrayBlockingQueue等。 - 核心线程池大小(corePoolSize): 在没有超时的情况下,线程池中保持的最小线程数。
- 最大线程池大小(maximumPoolSize): 线程池中能容纳的最大线程数。
- 线程工厂(ThreadFactory): 用于创建新线程。
- 拒绝策略(RejectedExecutionHandler): 当任务无法被执行时,线程池会调用拒绝策略处理这些任务。常见策略有
AbortPolicy、DiscardPolicy、DiscardOldestPolicy、CallerRunsPolicy。
- 任务队列(BlockingQueue workQueue): 保存等待执行的任务。常见的队列类型有
2. 线程池的工作流程
- 提交任务: 当任务被提交到线程池时,线程池根据当前的线程数量和任务队列的情况决定如何处理任务。
- 执行任务:
- 如果当前线程数小于
corePoolSize,线程池会创建一个新线程来处理任务。 - 如果当前线程数大于等于
corePoolSize且任务队列未满,任务会被放入任务队列中等待执行。 - 如果任务队列已满并且当前线程数小于
maximumPoolSize,线程池会创建新的线程来处理任务。 - 如果线程数达到
maximumPoolSize,且任务队列也满了,线程池会根据配置的拒绝策略来处理该任务。
- 如果当前线程数小于
3. 线程池的生命周期
- Running: 线程池初始化完成,能接受新任务,并能处理已加入队列的任务。
- Shutdown: 调用
shutdown()方法后,不再接受新任务,但会处理已经在队列中的任务。 - Stop: 调用
shutdownNow()方法后,线程池不再接受新任务,并尝试终止正在执行的任务。 - Terminated: 当所有任务执行完毕,且线程池中所有线程均被终止后,线程池会进入此状态。
4. 拒绝策略
- 当线程池达到
maximumPoolSize且队列已满时,线程池无法处理新的任务,便会触发拒绝策略。Java 提供了四种默认的拒绝策略:- AbortPolicy: 抛出
RejectedExecutionException异常。 - DiscardPolicy: 丢弃无法执行的任务,不做任何处理。
- DiscardOldestPolicy: 丢弃队列最前面的任务,并尝试重新提交当前任务。
- CallerRunsPolicy: 由调用线程处理该任务(即提交任务的线程)。
- AbortPolicy: 抛出
5. 线程池的优势
- 减少资源消耗: 通过复用线程,避免了频繁创建和销毁线程所带来的性能开销。
- 提高响应速度: 当任务到达时,线程池中已有线程可以立即执行任务,降低了延迟。
- 统一管理: 线程池可以统一管理和监控线程的使用情况,避免系统资源耗尽。
6. 示例代码
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60L, TimeUnit.SECONDS, // idle thread keep-alive time
new LinkedBlockingQueue<>(100), // workQueue
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy() // rejection policy
);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " is executing");
});
}
executorService.shutdown();
}
}
在这个例子中,线程池创建了一个核心池大小为 2,最大池大小为 4 的线程池,并配置了任务队列和拒绝策略。
7. 常见的线程池类型
- FixedThreadPool: 固定大小的线程池,适用于需要限制线程数量的场景。
- CachedThreadPool: 会根据需要创建新线程的线程池,适用于大量短期异步任务的场景。
- SingleThreadExecutor: 只有一个线程的线程池,确保所有任务按照顺序执行。
- ScheduledThreadPool: 用于执行定时任务或周期性任务的线程池。
通过理解线程池的工作原理,可以更好地管理并发任务,提高系统性能。