南充建网站的资料如何免费做网站推广的
线程池是Java多线程编程中的核心组件,用于管理线程的生命周期、复用线程资源,避免频繁创建和销毁线程带来的性能开销。在高并发场景(如Web服务器、微服务调用等)中,合理使用线程池能显著提升系统性能和稳定性。
1. 为什么需要线程池?
-  
问题:直接创建线程(
new Thread())的缺点:-  
线程创建和销毁开销大(涉及操作系统资源分配)。
 -  
无限制创建线程会导致资源耗尽(如内存溢出)。
 
 -  
 -  
解决方案:线程池通过复用线程、限制并发数、任务队列机制解决这些问题。
 
2. Java中的线程池实现
Java通过java.util.concurrent.ExecutorService接口及其实现类提供线程池支持,核心实现类是ThreadPoolExecutor。
2.1 线程池的创建(ThreadPoolExecutor)
ThreadPoolExecutor executor = new ThreadPoolExecutor(int corePoolSize,      // 核心线程数(长期存活的线程)int maximumPoolSize,   // 最大线程数(临时线程 = maximumPoolSize - corePoolSize)long keepAliveTime,    // 临时线程空闲存活时间TimeUnit unit,         // 时间单位(秒/毫秒等)BlockingQueue<Runnable> workQueue, // 任务队列RejectedExecutionHandler handler  // 拒绝策略
); 
关键参数说明
| 参数 | 作用 | 
|---|---|
corePoolSize | 核心线程数,即使空闲也不会被销毁(除非allowCoreThreadTimeOut=true)。 | 
maximumPoolSize | 线程池最大能容纳的线程数(核心线程 + 临时线程)。 | 
keepAliveTime | 临时线程空闲时的存活时间,超时后销毁。 | 
workQueue | 任务队列,用于存放待执行的任务(常见队列类型见下文)。 | 
handler | 当线程池和队列都满时,如何处理新任务(拒绝策略)。 | 
2.2 任务队列(BlockingQueue)类型
| 队列类型 | 特性 | 
|---|---|
ArrayBlockingQueue | 有界队列,固定大小,任务超出队列大小时会创建临时线程。 | 
LinkedBlockingQueue | 无界队列(默认Integer.MAX_VALUE),可能导致OOM。 | 
SynchronousQueue | 不存储任务,直接交给线程执行(需搭配maximumPoolSize使用)。 | 
PriorityBlockingQueue | 带优先级的无界队列(任务需实现Comparable)。 | 
2.3 拒绝策略(RejectedExecutionHandler)
当线程池和队列都满时,对新任务的处理方式:
| 策略名 | 行为 | 
|---|---|
AbortPolicy(默认) | 直接抛出RejectedExecutionException。 | 
CallerRunsPolicy | 让提交任务的线程自己执行该任务(同步执行)。 | 
DiscardPolicy | 静默丢弃任务,不抛异常。 | 
DiscardOldestPolicy | 丢弃队列中最旧的任务,然后重新尝试提交当前任务。 | 
3. 线程池的工作流程
-  
提交任务:调用
executor.execute(Runnable task)或submit(Callable task)。 -  
线程分配:
-  
如果当前线程数 <
corePoolSize,立即创建新线程执行任务。 -  
如果线程数 ≥
corePoolSize,任务进入workQueue等待。 -  
如果队列已满且线程数 <
maximumPoolSize,创建临时线程执行任务。 -  
如果队列和线程池均满,触发
拒绝策略。 
 -  
 -  
线程回收:
-  
核心线程默认长期存活。
 -  
临时线程在空闲
keepAliveTime后被销毁。 
 -  
 
4. 常见的线程池工具类(Executors)
Java提供了Executors工具类快速创建线程池(但需注意潜在问题):
| 方法名 | 底层实现 | 问题 | 
|---|---|---|
newFixedThreadPool(int n) | 固定大小的线程池(核心=最大线程数,无界队列) | 无界队列可能导致OOM。 | 
newCachedThreadPool() | 可扩容线程池(核心=0,最大=Integer.MAX_VALUE) | 线程数无限制,可能创建过多线程导致资源耗尽。 | 
newSingleThreadExecutor() | 单线程池(核心=最大=1,无界队列) | 无界队列可能导致OOM。 | 
newScheduledThreadPool() | 支持定时/周期性任务的线程池。 | 无界队列可能导致OOM。 | 
建议:生产环境推荐手动创建
ThreadPoolExecutor,避免使用Executors的无界队列。
5. 线程池的最佳实践
-  
合理配置参数:
-  
CPU密集型任务:
corePoolSize = CPU核心数 + 1。 -  
IO密集型任务:
corePoolSize = 2 * CPU核心数。 
 -  
 -  
避免无界队列:使用
ArrayBlockingQueue或自定义有界队列。 -  
明确拒绝策略:根据业务选择
AbortPolicy(日志记录 + 告警)或CallerRunsPolicy。 -  
监控线程池:通过
ThreadPoolExecutor的方法(如getActiveCount())或Spring Boot Actuator。 
6. 示例代码
// 手动创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(2,                              // corePoolSize5,                              // maximumPoolSize60, TimeUnit.SECONDS,           // keepAliveTimenew ArrayBlockingQueue<>(10),   // 有界队列(容量10)new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);// 提交任务
executor.execute(() -> {System.out.println("Task executed by " + Thread.currentThread().getName());
});// 关闭线程池(平滑关闭)
executor.shutdown(); 
7. 常见面试题
-  
线程池的底层原理是什么?
 -  
corePoolSize和maximumPoolSize如何协作? -  
无界队列会导致什么问题?
 -  
如何优化线程池参数?
 -  
线程池的拒绝策略有哪些?如何选择?
 
掌握线程池是Java高并发编程的基础,也是面试高频考点。建议结合源码(如ThreadPoolExecutor)和实际场景(如Web服务器请求处理)加深理解。
