Java创建【线程池】的方法
在Java中,创建线程池主要通过 java.util.concurrent 包下的 ThreadPoolExecutor 类 或其封装工具类 Executors 实现。线程池的核心作用是复用线程、控制并发数、减少线程创建销毁的开销,是处理多线程任务的最佳实践。
一、核心方式:ThreadPoolExecutor(推荐)
ThreadPoolExecutor 是线程池的核心实现类,提供了最灵活的参数配置,能根据业务场景精确控制线程池行为。其构造方法如下:
public ThreadPoolExecutor(int corePoolSize,                   // 核心线程数int maximumPoolSize,                // 最大线程数long keepAliveTime,                 // 非核心线程空闲超时时间TimeUnit unit,                      // 超时时间单位(如秒、毫秒)BlockingQueue<Runnable> workQueue,  // 工作队列(存放等待执行的任务)ThreadFactory threadFactory,        // 线程工厂(用于创建线程)RejectedExecutionHandler handler    // 拒绝策略(任务满时如何处理新任务)
)
1. 核心参数详解(必须掌握)
- 
corePoolSize(核心线程数):
 线程池长期保持的线程数量(即使线程空闲也不会销毁,除非设置了allowCoreThreadTimeOut)。
 例如:设置为5,表示线程池至少有5个线程随时待命。
- 
maximumPoolSize(最大线程数):
 线程池允许创建的最大线程数(核心线程 + 非核心线程的总和)。当工作队列满了,且当前线程数 < 最大线程数时,会创建新的非核心线程处理任务。
- 
keepAliveTime+unit(空闲超时时间):
 非核心线程的空闲时间阈值,超过这个时间会被销毁(释放资源)。核心线程默认不会超时销毁,可通过allowCoreThreadTimeOut(true)开启核心线程超时。
- 
workQueue(工作队列):
 用于存放等待执行的任务的阻塞队列,常见实现:- LinkedBlockingQueue:无界队列(默认大小 Integer.MAX_VALUE,可能导致OOM);
- ArrayBlockingQueue:有界队列(需指定大小,如- new ArrayBlockingQueue<>(100));
- SynchronousQueue:同步队列(不存储任务,直接传递给线程,适合任务量大但执行快的场景)。
 
- 
threadFactory(线程工厂):
 用于创建线程的工厂,可自定义线程名称(方便排查问题)、优先级等。默认使用Executors.defaultThreadFactory()。
- 
handler(拒绝策略):
 当线程池已满(线程数达最大 + 队列满),新任务的处理策略,JDK 提供4种默认策略:- AbortPolicy(默认):直接抛出- RejectedExecutionException异常;
- CallerRunsPolicy:让提交任务的线程自己执行(减缓提交速度,起到缓冲作用);
- DiscardPolicy:直接丢弃新任务,不抛异常;
- DiscardOldestPolicy:丢弃队列中最旧的任务,再尝试提交新任务。
 
2. 示例:用 ThreadPoolExecutor 创建线程池
import java.util.concurrent.*;public class ThreadPoolExample {public static void main(String[] args) {// 1. 配置线程池参数int corePoolSize = 5;                  // 核心线程数5int maximumPoolSize = 10;              // 最大线程数10long keepAliveTime = 60;               // 非核心线程空闲60秒后销毁TimeUnit unit = TimeUnit.SECONDS;      // 时间单位:秒BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(20); // 有界队列,容量20ThreadFactory threadFactory = Executors.defaultThreadFactory();  // 默认线程工厂RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy(); // 拒绝策略// 2. 创建线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);// 3. 提交任务(示例:执行100个任务)for (int i = 0; i < 100; i++) {int taskId = i;executor.execute(() -> {  // 提交Runnable任务System.out.println("任务" + taskId + "执行,线程:" + Thread.currentThread().getName());try {Thread.sleep(100); // 模拟任务执行} catch (InterruptedException e) {e.printStackTrace();}});}// 4. 关闭线程池(所有任务执行完后关闭)executor.shutdown();}
}
二、便捷方式:Executors 工具类(需谨慎使用)
Executors 提供了几种预配置的线程池,简化了创建过程,但存在资源耗尽风险(如无界队列导致OOM),生产环境推荐手动配置 ThreadPoolExecutor。
1. Executors.newFixedThreadPool(n):固定大小线程池
- 特点:核心线程数 = 最大线程数 = n,队列是无界的 LinkedBlockingQueue。
- 适用场景:任务数量稳定,需要控制并发数的场景(如服务器接收固定数量的请求)。
- 示例:ExecutorService fixedPool = Executors.newFixedThreadPool(5); // 5个固定线程
2. Executors.newCachedThreadPool():可缓存线程池
- 特点:核心线程数=0,最大线程数=Integer.MAX_VALUE(几乎无限),空闲线程60秒后销毁,队列是 SynchronousQueue(不存任务)。
- 适用场景:短期、轻量任务(如临时处理一批小任务),线程数随任务量动态增减。
- 风险:任务过多时可能创建大量线程,导致CPU/内存耗尽。
- 示例:ExecutorService cachedPool = Executors.newCachedThreadPool();
3. Executors.newSingleThreadExecutor():单线程线程池
- 特点:核心线程数=1,最大线程数=1,队列无界,所有任务按顺序执行(串行)。
- 适用场景:需要任务顺序执行的场景(如日志写入、单线程处理避免并发问题)。
- 示例:ExecutorService singlePool = Executors.newSingleThreadExecutor();
4. Executors.newScheduledThreadPool(n):定时任务线程池
- 特点:核心线程数=n,支持定时/周期性执行任务(如延迟3秒执行,或每隔1分钟执行一次)。
- 适用场景:定时任务(如定时备份数据、定时发送消息)。
- 示例:ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3); // 延迟2秒执行任务 scheduledPool.schedule(() -> System.out.println("延迟执行"), 2, TimeUnit.SECONDS); // 延迟1秒后,每隔3秒执行一次 scheduledPool.scheduleAtFixedRate(() -> System.out.println("周期执行"), 1, 3, TimeUnit.SECONDS);
三、为什么推荐 ThreadPoolExecutor 而非 Executors?
Executors 创建的线程池存在隐藏风险:
- newFixedThreadPool和- newSingleThreadExecutor使用无界队列(- LinkedBlockingQueue),当任务过多时,队列会无限增长,导致堆内存溢出(OOM);
- newCachedThreadPool的最大线程数是- Integer.MAX_VALUE,任务激增时可能创建数万线程,耗尽CPU和内存。
而 ThreadPoolExecutor 允许手动配置有界队列和合理的最大线程数,能有效控制资源消耗,避免OOM。
四、线程池的关闭
线程池不会自动关闭,需手动调用关闭方法:
- executor.shutdown():平缓关闭,等待已提交的任务执行完,不再接收新任务;
- executor.shutdownNow():立即关闭,尝试中断正在执行的任务,返回未执行的任务列表。
总结
创建线程池的核心是通过 ThreadPoolExecutor 手动配置参数(核心线程数、最大线程数、有界队列、拒绝策略等),根据业务场景(任务类型、并发量、资源限制)合理设置,避免使用 Executors 带来的资源风险。线程池的核心价值是复用线程、控制并发,是高并发场景下的必备工具。
