Files
interview/questions/05-并发编程/线程池核心参数.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
Organized 50 interview questions into 12 categories:
- 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc.
- 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理
- 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc.
- 04-消息队列 (1 file): RocketMQ/Kafka
- 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc.
- 06-JVM (1 file): JVM和垃圾回收
- 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc.
- 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮
- 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化
- 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx
- 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性
- 12-面试技巧 (1 file): 面试技巧和职业规划

All files renamed to Chinese for better accessibility and
organized into categorized folders for easier navigation.

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:10:53 +08:00

601 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 线程池核心参数详解
## 问题
1. 线程池的核心参数有哪些?各自的作用是什么?
2. 如何合理设置线程池大小?
3. 线程池的拒绝策略有哪些?如何自定义?
4. 线程池如何优雅关闭?
5. 线程池的监控指标有哪些?
6. 在实际项目中如何使用线程池?
---
## 标准答案
### 1. 线程池核心参数
#### **ThreadPoolExecutor 构造函数**
```java
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
```
---
#### **参数详解**
**1. corePoolSize核心线程数**
- **说明**:即使空闲也保留的线程数
- **默认值**:创建时无核心线程(任务到达时才创建)
- **预热**`prestartAllCoreThreads()` 提前创建核心线程
```java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, // 核心线程数
20, // 最大线程数
...
);
// 预热核心线程
executor.prestartAllCoreThreads();
```
---
**2. maximumPoolSize最大线程数**
- **说明**:线程池允许的最大线程数
- **限制**`maximumPoolSize >= corePoolSize`
- **动态调整**:运行时可通过 `setMaximumPoolSize()` 调整
```java
// 动态调整最大线程数
executor.setMaximumPoolSize(50);
```
---
**3. keepAliveTime非核心线程存活时间**
- **说明**:非核心线程的空闲存活时间
- **超时回收**:超过时间后,线程会被回收
- **允许回收核心线程**`allowCoreThreadTimeOut(true)`
```java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10,
20,
60, // 存活时间
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100)
);
// 允许核心线程超时回收
executor.allowCoreThreadTimeOut(true);
```
---
**4. workQueue任务队列**
**常见队列**
| 队列 | 特性 | 适用场景 |
|------|------|----------|
| **SynchronousQueue** | 不存储,直接传递 | 高并发、低延迟 |
| **LinkedBlockingQueue** | 无界队列(默认 Integer.MAX_VALUE | 任务提交频繁 |
| **ArrayBlockingQueue** | 有界队列 | 防止资源耗尽 |
| **PriorityBlockingQueue** | 优先级队列 | 优先级任务 |
**示例**
```java
// 1. SynchronousQueue高并发
ExecutorService executor1 = new ThreadPoolExecutor(
10, 20,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>() // 无队列,直接传递
);
// 2. LinkedBlockingQueue无界
ExecutorService executor2 = new ThreadPoolExecutor(
10, 20,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000) // 队列长度 1000
);
// 3. PriorityBlockingQueue优先级
ExecutorService executor3 = new ThreadPoolExecutor(
10, 20,
60L, TimeUnit.SECONDS,
new PriorityBlockingQueue<>(100)
);
```
---
**5. threadFactory线程工厂**
**作用**
- 设置线程名称(便于排查)
- 设置线程优先级
- 设置是否为守护线程
**示例**
```java
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("order-pool-%d") // 线程名称前缀
.setDaemon(false) // 非守护线程
.setPriority(Thread.NORM_PRIORITY)
.build();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 20,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
namedThreadFactory
);
```
---
**6. handler拒绝策略**
**内置策略**
| 策略 | 说明 |
|------|------|
| **AbortPolicy默认** | 抛出异常 |
| **CallerRunsPolicy** | 调用者线程执行 |
| **DiscardPolicy** | 静默丢弃 |
| **DiscardOldestPolicy** | 丢弃最旧的任务 |
```java
// 自定义拒绝策略
RejectedExecutionHandler handler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 记录日志
log.warn("任务被拒绝: {}", r);
// 重试(加入队列等待)
if (!executor.isShutdown()) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
};
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 20,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
handler
);
```
---
### 2. 线程池工作流程
```
任务提交
核心线程数 < corePoolSize
├─ 是 → 创建核心线程并执行
└─ 否 → 继续
队列未满?
├─ 是 → 加入队列
└─ 否 → 继续
线程数 < maximumPoolSize
├─ 是 → 创建非核心线程并执行
└─ 否 → 继续
拒绝策略
```
---
### 3. 合理设置线程池大小
#### **CPU 密集型任务**
**特点**:主要消耗 CPU 资源(计算、加密)
**公式**
```
线程数 = CPU 核心数 + 1
```
**原因**
- CPU 密集型任务不需要太多线程
- +1 是为了当某线程因页故障等原因暂停时CPU 不会闲置
**示例**
```java
int cpuCore = Runtime.getRuntime().availableProcessors(); // 8
int poolSize = cpuCore + 1; // 9
ThreadPoolExecutor executor = new ThreadPoolExecutor(
poolSize, // 核心线程数
poolSize, // 最大线程数
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(100)
);
```
---
#### **IO 密集型任务**
**特点**:主要等待 IO网络、磁盘
**公式**
```
线程数 = CPU 核心数 × (1 + IO 耗时 / CPU 耗时)
```
**示例**
```java
// IO 耗时 / CPU 耗时 = 2IO 占 2/3CPU 占 1/3
int cpuCore = Runtime.getRuntime().availableProcessors(); // 8
int poolSize = cpuCore * (1 + 2); // 24
ThreadPoolExecutor executor = new ThreadPoolExecutor(
cpuCore, // 核心线程数 = CPU 核心数
poolSize, // 最大线程数
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(500)
);
```
---
#### **通用公式**
```
线程数 = CPU 核心数 × 目标 CPU 使用率 × (1 + IO 耗时 / CPU 耗时)
```
**参数调整**
- 目标 CPU 使用率80% - 90%
- IO / CPU 比例:通过压测获得
---
### 4. 线程池监控
#### **监控指标**
| 指标 | 说明 | 获取方法 |
|------|------|----------|
| **活跃线程数** | 正在执行任务的线程数 | `getActiveCount()` |
| **已完成任务数** | 历史完成的任务总数 | `getCompletedTaskCount()` |
| **总任务数** | 已完成 + 正在执行 | `getTaskCount()` |
| **队列大小** | 队列中待执行任务数 | `getQueue().size()` |
| **最大线程数** | 历史最大线程数 | `getLargestPoolSize()` |
| **线程池是否关闭** | `isShutdown()` | `isShutdown()` |
---
#### **监控代码**
```java
@Component
public class ThreadPoolMonitor {
@Autowired
private Map<String, ThreadPoolExecutor> executorMap;
@Scheduled(fixedRate = 60000) // 每分钟
public void monitor() {
executorMap.forEach((name, executor) -> {
ThreadPoolExecutorStats stats = new ThreadPoolExecutorStats();
stats.setName(name);
stats.setCorePoolSize(executor.getCorePoolSize());
stats.setMaximumPoolSize(executor.getMaximumPoolSize());
stats.setActiveCount(executor.getActiveCount());
stats.setCompletedTaskCount(executor.getCompletedTaskCount());
stats.setTaskCount(executor.getTaskCount());
stats.setQueueSize(executor.getQueue().size());
stats.setLargestPoolSize(executor.getLargestPoolSize());
// 上报到监控系统Prometheus、Grafana
Metrics.report(stats);
// 告警判断
if (executor.getActiveCount() >= executor.getMaximumPoolSize() * 0.8) {
alert("线程池 " + name + " 负载过高");
}
});
}
}
```
---
#### **Actuator 监控Spring Boot**
**依赖**
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
```
**配置**
```yaml
management:
endpoints:
web:
exposure:
include: health,info,metrics
metrics:
export:
prometheus:
enabled: true
```
**访问**
```bash
curl http://localhost:8080/actuator/metrics
curl http://localhost:8080/actuator/metrics/executor.pool.size
```
---
### 5. 线程池优雅关闭
#### **问题**
不优雅关闭的后果:
- 已提交的任务可能丢失
- 正在执行的任务可能被中断
---
#### **shutdown()**
```java
executor.shutdown();
try {
// 等待任务完成
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
// 超时,强制关闭
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
```
**特点**
- 不再接受新任务
- 等待已提交的任务完成
- 超时后可调用 `shutdownNow()` 强制关闭
---
#### **shutdownNow()**
```java
List<Runnable> unfinishedTasks = executor.shutdownNow();
```
**特点**
- 不再接受新任务
- 尝试停止正在执行的任务(通过 `Thread.interrupt()`
- 返回未执行的任务列表
---
### 6. Spring 线程池配置
#### **配置类**
```java
@Configuration
public class ThreadPoolConfig {
@Bean("orderThreadPool")
public ThreadPoolExecutor orderThreadPool() {
return new ThreadPoolExecutor(
10, // 核心线程数
20, // 最大线程数
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new ThreadFactoryBuilder()
.setNameFormat("order-pool-%d")
.build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
@Bean("emailThreadPool")
public ThreadPoolExecutor emailThreadPool() {
return new ThreadPoolExecutor(
5,
10,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(50),
new ThreadFactoryBuilder()
.setNameFormat("email-pool-%d")
.build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
```
---
#### **使用**
```java
@Service
public class OrderService {
@Autowired
@Qualifier("orderThreadPool")
private ThreadPoolExecutor orderThreadPool;
public void createOrder(Order order) {
// 异步处理
orderThreadPool.execute(() -> {
// 处理订单
processOrder(order);
});
}
}
```
---
#### **@AsyncSpring 异步)**
**配置**
```java
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-pool-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
```
**使用**
```java
@Service
public class EmailService {
@Async("asyncExecutor")
public void sendEmail(String to, String subject, String body) {
// 异步发送邮件
mailSender.send(to, subject, body);
}
}
```
---
### 7. 实际项目经验
#### **案例 1线程池参数调优**
**问题**
- 订单接口响应慢
- CPU 使用率低30%),线程池队列满
**分析**
```java
// 原配置
corePoolSize = 5
maximumPoolSize = 10
queue = LinkedBlockingQueue(100)
```
**问题**
- 线程数太少,任务堆积在队列
- 数据库连接池用满,等待连接
**优化**
```java
// 优化后配置
corePoolSize = 20 // 增加
maximumPoolSize = 50 // 增加
queue = LinkedBlockingQueue(500) // 增加
```
**结果**:响应时间从 2s 降至 200ms
---
#### **案例 2动态线程池**
**需求**:根据流量动态调整线程池大小
**实现**
```java
@Component
public class DynamicThreadPoolManager {
private final Map<String, ThreadPoolExecutor> executorMap = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
// 定时调整线程池大小
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this::adjustThreadPoolSize, 1, 1, TimeUnit.MINUTES);
}
private void adjustThreadPoolSize() {
executorMap.forEach((name, executor) -> {
// 获取当前负载
int activeCount = executor.getActiveCount();
int maximumPoolSize = executor.getMaximumPoolSize();
// 负载 > 80%,扩容
if (activeCount > maximumPoolSize * 0.8) {
int newSize = Math.min(maximumPoolSize * 2, 100);
executor.setMaximumPoolSize(newSize);
log.info("扩容线程池: {} -> {}", name, newSize);
}
// 负载 < 20%,缩容
else if (activeCount < maximumPoolSize * 0.2) {
int newSize = Math.max(maximumPoolSize / 2, executor.getCorePoolSize());
executor.setMaximumPoolSize(newSize);
log.info("缩容线程池: {} -> {}", name, newSize);
}
});
}
}
```
---
### 8. 阿里 P7 加分项
**深度理解**
- 理解线程池的状态转换RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED
- 理解 `Worker` 的实现原理(继承 AQS、实现 Runnable
- 理解线程池的异常处理机制
**实战经验**
- 有线程池参数调优的经验
- 有处理线程池饱和问题的经验
- 有线程池监控和告警的经验
**架构能力**
- 能设计动态线程池(根据流量调整)
- 能设计线程池隔离(不同业务独立线程池)
- 能设计线程池监控体系
**技术选型**
- 了解 `ForkJoinPool`(工作窃取线程池)
- 了解 `ScheduledThreadPoolExecutor`(定时任务线程池)
- 了解 `Vert.x`、WebFlux 等响应式框架的线程模型