Java 线程池(Thread Pool) 一、什么是线程池 线程池 是一种线程管理机制,用于提前创建并复用固定数量的线程,以避免频繁地创建/销毁线程带来的资源开销。
主要优势包括:
降低资源消耗(复用线程)
提高响应速度(任务提交后可立即执行)
方便管理线程(线程数可控,支持超时、拒绝策略等)
二、线程池的核心类:Executor
和 ThreadPoolExecutor
Java 中的线程池定义在 java.util.concurrent
包下,主要接口和类包括:
接口/类名
说明
Executor
线程池顶层接口,定义任务执行方法
ExecutorService
扩展接口,支持任务返回值、关闭池
ThreadPoolExecutor
线程池的核心实现类
Executors
工厂类,用于创建常见线程池
Future
代表异步任务结果
三、使用线程池的三种方式 1. 使用 Executors
工厂类(不推荐用于生产) 1 2 3 4 5 6 7 java复制编辑ExecutorService pool = Executors.newFixedThreadPool(5); pool.execute(() -> { System.out.println(Thread.currentThread().getName() + " 执行任务"); }); pool.shutdown();
Executors
提供的几种线程池:
方法
描述
newFixedThreadPool(n)
固定大小线程池
newCachedThreadPool()
可自动扩容线程池(适合短任务)
newSingleThreadExecutor()
单线程池
newScheduledThreadPool(n)
定时/周期性任务线程池
说明:Executors
默认使用 无界队列 (如 LinkedBlockingQueue),在任务过多时容易导致内存溢出。推荐手动使用 ThreadPoolExecutor 。
2. 手动创建 ThreadPoolExecutor
(推荐) 1 2 3 4 5 6 7 8 9 java复制编辑ExecutorService pool = new ThreadPoolExecutor( 2, // corePoolSize 核心线程数 5, // maximumPoolSize 最大线程数 60L, // keepAliveTime 空闲线程最大存活时间 TimeUnit.SECONDS, // 时间单位 new ArrayBlockingQueue<>(10), // 等待队列(有界) Executors.defaultThreadFactory(), // 线程工厂 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 );
四、线程池任务执行流程
任务提交给线程池
如果线程数 < corePoolSize,创建新线程执行任务
如果线程数 ≥ corePoolSize,任务放入队列等待
如果队列已满且线程数 < maximumPoolSize,创建新线程执行任务
如果队列已满且线程数达到最大,触发拒绝策略
五、拒绝策略(RejectedExecutionHandler) 当线程池和队列都满了时,线程池会调用 拒绝策略 :
策略类
描述
AbortPolicy
(默认)
抛出 RejectedExecutionException
CallerRunsPolicy
由提交任务的线程(主线程)执行该任务
DiscardPolicy
直接丢弃任务
DiscardOldestPolicy
丢弃队列中最早的任务,尝试执行当前任务
六、线程池常用方法 1 2 3 4 5 6 7 java复制编辑Future<String> future = pool.submit(() -> { return "任务执行结果"; }); System.out.println(future.get()); // 获取返回值(阻塞) java复制编辑pool.shutdown(); // 平滑关闭线程池 pool.shutdownNow(); // 立即关闭线程池(中断正在执行的线程)
七、线程池参数调优建议
参数
调优建议
corePoolSize
根据 CPU 核数和任务类型(I/O密集 or 计算密集)
maximumPoolSize
通常是 core 数的 1.5 ~ 2 倍
队列类型
推荐使用有界队列(如 ArrayBlockingQueue)
拒绝策略
根据业务场景选择(如降级、记录日志)
keepAliveTime
非核心线程空闲存活时间
八、实际开发中的应用场景
Web 服务器处理请求(如 Tomcat 使用线程池处理 Servlet 请求)
数据库连接池底层使用线程池管理连接
消息处理系统(异步处理消息队列中的任务)
定时任务调度(使用 ScheduledExecutorService
)
九、示例:批量执行任务并收集返回值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 java复制编辑ExecutorService pool = Executors.newFixedThreadPool(3); List<Future<Integer>> futures = new ArrayList<>(); for (int i = 0; i < 5; i++) { int num = i; futures.add(pool.submit(() -> { Thread.sleep(1000); return num * num; })); } for (Future<Integer> f : futures) { System.out.println("结果:" + f.get()); } pool.shutdown();
十、补充:线程池监控与可视化 可以通过以下方式监控线程池运行状态:
1 2 3 4 5 6 java复制编辑ThreadPoolExecutor pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(3); System.out.println(pool.getPoolSize()); // 当前线程池大小 System.out.println(pool.getActiveCount()); // 活跃线程数 System.out.println(pool.getQueue().size()); // 队列长度 System.out.println(pool.getCompletedTaskCount());// 完成任务数