Java线程池
Java线程池[编辑 | 编辑源代码]
简介[编辑 | 编辑源代码]
Java线程池是Java多线程编程中的核心组件,它通过复用线程来减少创建和销毁线程的开销,提高系统性能和资源利用率。线程池属于`java.util.concurrent`包的一部分,是Executor框架的核心实现。
线程池的主要优势包括:
- 资源节约:避免频繁创建/销毁线程
- 性能提升:减少线程创建延迟
- 线程管理:提供统一的线程生命周期控制
- 任务队列:支持任务缓冲和调度
核心概念[编辑 | 编辑源代码]
线程池组成[编辑 | 编辑源代码]
Java线程池主要由以下组件构成: 1. 工作线程(Worker Threads):执行任务的线程 2. 任务队列(BlockingQueue):存放待执行任务 3. 线程工厂(ThreadFactory):创建新线程 4. 拒绝策略(RejectedExecutionHandler):处理无法执行的任务
线程池类型[编辑 | 编辑源代码]
Java通过`Executors`类提供了几种常用线程池:
1. 固定大小线程池[编辑 | 编辑源代码]
```java ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); ```
- 特点:固定数量的线程
- 适用场景:已知并发量的稳定负载
2. 可缓存线程池[编辑 | 编辑源代码]
```java ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); ```
- 特点:自动扩展/收缩线程数
- 适用场景:大量短期异步任务
3. 单线程池[编辑 | 编辑源代码]
```java ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); ```
- 特点:单线程顺序执行
- 适用场景:需要任务顺序执行的场景
4. 定时线程池[编辑 | 编辑源代码]
```java ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3); ```
- 特点:支持定时/周期性任务
- 适用场景:定时任务、延迟任务
核心参数详解[编辑 | 编辑源代码]
通过`ThreadPoolExecutor`构造函数可自定义线程池:
```java public ThreadPoolExecutor(
int corePoolSize, // 核心线程数 int maximumPoolSize, // 最大线程数 long keepAliveTime, // 空闲线程存活时间 TimeUnit unit, // 时间单位 BlockingQueue<Runnable> workQueue, // 任务队列 ThreadFactory threadFactory, // 线程工厂 RejectedExecutionHandler handler // 拒绝策略
) ```
参数配置示例[编辑 | 编辑源代码]
```java ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数 5, // 最大线程数 60, // 空闲时间 TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), // 容量为10的队列 Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy() // 默认拒绝策略
); ```
任务执行流程[编辑 | 编辑源代码]
1. 任务提交后,优先使用核心线程执行 2. 核心线程忙时,任务进入队列 3. 队列满时,创建非核心线程(不超过maximumPoolSize) 4. 线程数达最大值且队列满时,触发拒绝策略
拒绝策略[编辑 | 编辑源代码]
Java提供四种内置拒绝策略: 1. AbortPolicy:默认策略,抛出RejectedExecutionException 2. CallerRunsPolicy:由提交任务的线程直接执行 3. DiscardPolicy:静默丢弃任务 4. DiscardOldestPolicy:丢弃队列中最旧的任务
代码示例[编辑 | 编辑源代码]
基础使用示例[编辑 | 编辑源代码]
```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) { // 创建固定大小的线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 提交10个任务 for (int i = 1; i <= 10; i++) { final int taskId = i; executor.execute(() -> { System.out.println("执行任务 " + taskId + " 线程: " + Thread.currentThread().getName()); try { Thread.sleep(1000); // 模拟任务耗时 } catch (InterruptedException e) { e.printStackTrace(); } }); } // 关闭线程池 executor.shutdown(); }
} ```
输出示例: ``` 执行任务 1 线程: pool-1-thread-1 执行任务 2 线程: pool-1-thread-2 执行任务 3 线程: pool-1-thread-3 执行任务 4 线程: pool-1-thread-1 执行任务 5 线程: pool-1-thread-2 ... ```
自定义线程池示例[编辑 | 编辑源代码]
```java import java.util.concurrent.*;
public class CustomThreadPool {
public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, 4, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), new ThreadPoolExecutor.CallerRunsPolicy() ); for (int i = 1; i <= 8; i++) { final int taskId = i; executor.execute(() -> { System.out.println("任务 " + taskId + " 由 " + Thread.currentThread().getName() + " 执行"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } }); System.out.println("队列大小: " + executor.getQueue().size()); } executor.shutdown(); }
} ```
最佳实践[编辑 | 编辑源代码]
1. 合理配置线程数:
* CPU密集型任务: * IO密集型任务:
2. 避免使用无界队列:可能导致内存溢出
3. 正确处理异常: ```java executor.submit(() -> {
try { // 任务代码 } catch (Exception e) { // 异常处理 }
}); ```
4. 优雅关闭: ```java executor.shutdown(); // 平缓关闭 executor.shutdownNow(); // 立即关闭 ```
实际应用场景[编辑 | 编辑源代码]
Web服务器请求处理[编辑 | 编辑源代码]
典型的三层线程池架构: 1. 接收层:单线程接受连接 2. 处理层:线程池处理请求 3. IO层:专用线程池处理阻塞IO
批量数据处理[编辑 | 编辑源代码]
```java // 处理10000条数据 List dataList = getDataList(); ExecutorService executor = Executors.newFixedThreadPool(8);
List<Future<Result>> futures = new ArrayList<>(); for (Data data : dataList) {
futures.add(executor.submit(() -> processData(data)));
}
// 获取结果 for (Future<Result> future : futures) {
Result result = future.get(); // 处理结果
} ```
常见问题[编辑 | 编辑源代码]
线程池大小选择[编辑 | 编辑源代码]
- 太小:无法充分利用CPU
- 太大:增加上下文切换开销
任务堆积处理[编辑 | 编辑源代码]
- 监控队列大小:`executor.getQueue().size()`
- 动态调整线程数:`executor.setCorePoolSize()`
死锁风险[编辑 | 编辑源代码]
避免任务间相互等待,特别是在使用同线程池时
性能监控[编辑 | 编辑源代码]
可通过以下方法监控线程池状态: ```java // 活动线程数 int activeCount = executor.getActiveCount();
// 已完成任务数 long completedTaskCount = executor.getCompletedTaskCount();
// 队列中的任务数 int queueSize = executor.getQueue().size(); ```
总结[编辑 | 编辑源代码]
Java线程池是多线程编程的强大工具,正确使用可以:
- 提高系统吞吐量
- 降低资源消耗
- 提供更好的可管理性
关键点:
- 根据场景选择合适的线程池类型
- 合理配置核心参数
- 实现适当的拒绝策略
- 监控和调优线程池性能