### 线程池的核心原理
线程池通过预先创建一定数量的线程并维护这些线程的生命周期,实现对线程的复用,从而避免频繁创建和销毁线程带来的性能开销。Java中的`ThreadPoolExecutor`是线程池的核心实现类,其构造函数包含以下关键参数:
- corePoolSize:核心线程数,即使线程空闲也不会被回收,除非设置`allowCoreThreadTimeOut`为true
- maximumPoolSize:最大线程数,当工作队列满时创建的新线程上限
- keepAliveTime:非核心线程空闲时的存活时间
- workQueue:用于存放待执行任务的工作队列
- threadFactory:线程工厂,用于创建新线程
- handler:拒绝策略,当线程池和工作队列都满时的处理方式
### 线程池工作流程
1. 任务提交:当新任务提交时,线程池首先检查当前线程数是否小于corePoolSize
2. 核心线程创建:若小于,则创建新线程执行任务
3. 队列等待:若达到corePoolSize,则将任务放入工作队列
4. 非核心线程创建:若队列已满且线程数小于maximumPoolSize,创建新线程执行任务
5. 拒绝策略:若队列满且达到maximumPoolSize,执行拒绝策略
### 性能优化策略
#### 1. 合理配置线程池参数
核心线程数计算:
```java
// CPU密集型任务
int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
// I/O密集型任务
int corePoolSize = Runtime.getRuntime().availableProcessors() 2;
```
队列选择策略:
- `LinkedBlockingQueue`:无界队列,适合任务执行时间短、吞吐量高的场景
- `ArrayBlockingQueue`:有界队列,可防止资源耗尽
- `SynchronousQueue`:不存储元素,每个插入操作必须等待对应的移除操作
#### 2. 动态参数调整
```java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100)
);
// 动态调整核心线程数
executor.setCorePoolSize(4);
executor.setMaximumPoolSize(8);
```
#### 3. 监控与调优
线程池状态监控:
```java
// 获取线程池运行状态
int activeCount = executor.getActiveCount();
long completedTaskCount = executor.getCompletedTaskCount();
int queueSize = executor.getQueue().size();
```
自定义线程池:
```java
public class MonitoringThreadPool extends ThreadPoolExecutor {
@Override
protected void beforeExecute(Thread t, Runnable r) {
// 记录任务开始时间
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
// 记录任务执行时间、异常等信息
}
}
```
#### 4. 拒绝策略优化
自定义拒绝策略:
```java
public class CustomRejectionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 记录日志
// 持久化任务
// 或执行其他降级策略
if (!executor.isShutdown()) {
r.run();
}
}
}
```
#### 5. 资源清理与优雅关闭
```java
// 优雅关闭线程池
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
```
### 最佳实践
1. 避免使用无界队列:防止内存溢出
2. 合理设置线程存活时间:及时回收空闲线程
3. 使用有意义的线程名称:便于问题排查
4. 正确处理任务异常:避免线程因异常而退出
5. 考虑使用CompletableFuture:提供更灵活的任务编排能力
通过深入理解线程池的核心原理并实施合理的优化策略,可以显著提升Java并发程序的性能和稳定性,有效管理系统资源,避免常见的并发问题。
675

被折叠的 条评论
为什么被折叠?



