# 线程池

## 目录
- [线程池原理](#线程池原理)
- [线程池类型](#线程池类型)
- [线程池参数](#线程池参数)
- [线程池执行流程](#线程池执行流程)
- [线程池监控](#线程池监控)
- [线程池最佳实践](#线程池最佳实践)
- [面试常见问题](#面试常见问题)

---

## 线程池原理

### 为什么使用线程池？

```java
// ❌ 问题：频繁创建线程
for (int i = 0; i < 100; i++) {
    new Thread(() -> {
        // 执行任务
    }).start(); // 创建和销毁线程开销大
}

// ✅ 解决：使用线程池
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
    executor.execute(() -> {
        // 执行任务
    });
}
```

### 线程池优势

1. **降低资源消耗**：复用线程，减少创建和销毁开销
2. **提高响应速度**：任务到达时直接执行
3. **提高线程可管理性**：统一管理线程
4. **控制并发数**：限制同时执行的线程数

---

## 线程池类型

### 1. FixedThreadPool

```java
// 固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);

// 特点：
// - 核心线程数 = 最大线程数 = 5
// - 无界队列
// - 适合执行长期任务
```

### 2. CachedThreadPool

```java
// 缓存线程池
ExecutorService executor = Executors.newCachedThreadPool();

// 特点：
// - 核心线程数 = 0
// - 最大线程数 = Integer.MAX_VALUE
// - 适合执行短期任务
```

### 3. SingleThreadExecutor

```java
// 单线程线程池
ExecutorService executor = Executors.newSingleThreadExecutor();

// 特点：
// - 核心线程数 = 最大线程数 = 1
// - 无界队列
// - 任务按顺序执行
```

### 4. ScheduledThreadPool

```java
// 定时任务线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);

// 延迟执行
executor.schedule(() -> {
    // 执行任务
}, 1, TimeUnit.SECONDS);

// 周期性执行
executor.scheduleAtFixedRate(() -> {
    // 执行任务
}, 0, 1, TimeUnit.SECONDS);
```

---

## 线程池参数

### ThreadPoolExecutor 参数

```java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,        // 核心线程数
    maximumPoolSize,     // 最大线程数
    keepAliveTime,       // 空闲线程存活时间
    unit,                // 时间单位
    workQueue,           // 工作队列
    threadFactory,       // 线程工厂
    handler             // 拒绝策略
);
```

### 参数说明

#### 1. corePoolSize（核心线程数）

```java
// 核心线程数：即使空闲也保留的线程数
int corePoolSize = 5;
```

#### 2. maximumPoolSize（最大线程数）

```java
// 最大线程数：允许的最大线程数
int maximumPoolSize = 10;
```

#### 3. keepAliveTime（空闲线程存活时间）

```java
// 空闲线程存活时间：超过核心线程数的线程空闲多久后回收
long keepAliveTime = 60L;
TimeUnit unit = TimeUnit.SECONDS;
```

#### 4. workQueue（工作队列）

```java
// 工作队列类型
BlockingQueue<Runnable> workQueue;

// ArrayBlockingQueue：有界队列
workQueue = new ArrayBlockingQueue<>(100);

// LinkedBlockingQueue：无界队列
workQueue = new LinkedBlockingQueue<>();

// SynchronousQueue：同步队列
workQueue = new SynchronousQueue<>();
```

#### 5. threadFactory（线程工厂）

```java
// 自定义线程工厂
ThreadFactory threadFactory = new ThreadFactory() {
    private int count = 0;
    
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setName("MyThread-" + count++);
        return thread;
    }
};
```

#### 6. handler（拒绝策略）

```java
// 拒绝策略类型
RejectedExecutionHandler handler;

// AbortPolicy：抛出异常（默认）
handler = new ThreadPoolExecutor.AbortPolicy();

// CallerRunsPolicy：调用者执行
handler = new ThreadPoolExecutor.CallerRunsPolicy();

// DiscardPolicy：丢弃任务
handler = new ThreadPoolExecutor.DiscardPolicy();

// DiscardOldestPolicy：丢弃最老任务
handler = new ThreadPoolExecutor.DiscardOldestPolicy();
```

---

## 线程池执行流程

### 执行流程

```
1. 提交任务
2. 如果线程数 < corePoolSize，创建核心线程执行
3. 如果线程数 >= corePoolSize，将任务加入队列
4. 如果队列已满且线程数 < maximumPoolSize，创建新线程执行
5. 如果队列已满且线程数 >= maximumPoolSize，执行拒绝策略
```

### 流程图

```
任务提交
    ↓
线程数 < corePoolSize?
    ├─ 是 → 创建核心线程执行
    └─ 否 → 队列未满?
            ├─ 是 → 加入队列
            └─ 否 → 线程数 < maximumPoolSize?
                    ├─ 是 → 创建线程执行
                    └─ 否 → 执行拒绝策略
```

---

## 线程池监控

### 监控指标

```java
ThreadPoolExecutor executor = ...;

// 当前线程数
int poolSize = executor.getPoolSize();

// 活跃线程数
int activeCount = executor.getActiveCount();

// 已完成任务数
long completedTaskCount = executor.getCompletedTaskCount();

// 总任务数
long taskCount = executor.getTaskCount();

// 队列大小
int queueSize = executor.getQueue().size();
```

### 自定义监控

```java
public class MonitoredThreadPoolExecutor extends ThreadPoolExecutor {
    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        // 任务执行前
        Log.d("ThreadPool", "Task started: " + r);
    }
    
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        // 任务执行后
        Log.d("ThreadPool", "Task completed: " + r);
    }
    
    @Override
    protected void terminated() {
        super.terminated();
        // 线程池终止
        Log.d("ThreadPool", "ThreadPool terminated");
    }
}
```

---

## 线程池最佳实践

### 1. 合理设置参数

```java
// ✅ 好的配置
int corePoolSize = Runtime.getRuntime().availableProcessors();
int maximumPoolSize = corePoolSize * 2;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    60L,
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100),
    new ThreadPoolExecutor.CallerRunsPolicy()
);

// ❌ 不好的配置
ExecutorService executor = Executors.newCachedThreadPool();
// 可能创建过多线程
```

### 2. 使用有界队列

```java
// ✅ 使用有界队列
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(100);

// ❌ 使用无界队列可能导致内存溢出
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
```

### 3. 设置拒绝策略

```java
// 设置合适的拒绝策略
executor.setRejectedExecutionHandler(
    new ThreadPoolExecutor.CallerRunsPolicy()
);
```

### 4. 及时关闭线程池

```java
// 关闭线程池
executor.shutdown(); // 等待任务完成
// 或
executor.shutdownNow(); // 立即关闭
```

---

## 面试常见问题

### Q1: 为什么使用线程池？

**答案：**
1. 降低资源消耗：复用线程
2. 提高响应速度：任务到达直接执行
3. 提高线程可管理性：统一管理
4. 控制并发数：限制线程数

### Q2: 线程池的参数？

**答案：**
1. corePoolSize：核心线程数
2. maximumPoolSize：最大线程数
3. keepAliveTime：空闲线程存活时间
4. workQueue：工作队列
5. threadFactory：线程工厂
6. handler：拒绝策略

### Q3: 线程池执行流程？

**答案：**
1. 线程数 < corePoolSize：创建核心线程
2. 线程数 >= corePoolSize：加入队列
3. 队列满且线程数 < maximumPoolSize：创建新线程
4. 队列满且线程数 >= maximumPoolSize：执行拒绝策略

### Q4: 拒绝策略有哪些？

**答案：**
1. AbortPolicy：抛出异常
2. CallerRunsPolicy：调用者执行
3. DiscardPolicy：丢弃任务
4. DiscardOldestPolicy：丢弃最老任务

---

*最后更新：2024年*
