线程池有哪几种,怎么使用
线程池概述
- 定义:
- 线程池(Thread Pool)是一种管理线程的机制,通过维护一组预创建的线程来执行任务,避免频繁创建和销毁线程的开销,提高性能和资源利用率。
- Java 中线程池由
java.util.concurrent
包的Executor
框架提供,主要通过ThreadPoolExecutor
和Executors
工厂类实现。 - 核心作用:
- 性能优化:复用线程,减少创建/销毁开销。
- 资源控制:限制线程数量,避免系统过载。
- 任务管理:支持任务队列、拒绝策略、异步执行。
- 核心点:
- Java 提供多种线程池类型(如固定大小、缓存、单线程、定时任务),通过
Executors
创建,适用于不同场景。
1. Java 线程池的类型
Java 通过 Executors
工厂类提供以下几种常用线程池,每种适合特定场景:
(1) FixedThreadPool(固定大小线程池)
- 特点:
- 固定数量的线程(
nThreads
),任务队列无界(LinkedBlockingQueue
)。 - 线程数不变,适合长期运行的任务。
- 适用场景:
- 任务量稳定,需要控制并发线程数(如 Web 服务器)。
- 创建:
java ExecutorService executor = Executors.newFixedThreadPool(4); // 4 个线程
- 注意:
- 无界队列可能导致内存溢出(OOM),任务过多时需谨慎。
(2) CachedThreadPool(缓存线程池)
- 特点:
- 线程数动态调整(0 到
Integer.MAX_VALUE
),空闲线程存活 60 秒。 - 使用
SynchronousQueue
,任务直接交给线程,无队列存储。 - 适用场景:
- 短时突发任务,任务执行时间短(如轻量级异步任务)。
- 创建:
java ExecutorService executor = Executors.newCachedThreadPool();
- 注意:
- 线程数可能无限制增长,高并发下可能耗尽资源。
(3) SingleThreadExecutor(单线程池)
- 特点:
- 只有一个线程,按顺序执行任务,队列无界(
LinkedBlockingQueue
)。 - 保证任务串行执行。
- 适用场景:
- 需要严格顺序执行的任务(如日志写入、单线程事件处理)。
- 创建:
java ExecutorService executor = Executors.newSingleThreadExecutor();
- 注意:
- 单线程性能有限,任务积压可能导致延迟。
(4) ScheduledThreadPool(定时任务线程池)
- 特点:
- 支持定时和周期性任务执行,基于
DelayedWorkQueue
。 - 线程数固定或动态,适合调度任务。
- 适用场景:
- 定时任务、周期任务(如心跳检测、定时清理)。
- 创建:
java ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); // 2 个线程
- 方法:
schedule(Runnable, delay, TimeUnit)
:延迟执行。scheduleAtFixedRate(Runnable, initialDelay, period, TimeUnit)
:固定频率。scheduleWithFixedDelay(Runnable, initialDelay, delay, TimeUnit)
:固定间隔。- 示例:
java executor.schedule(() -> System.out.println("Task"), 1, TimeUnit.SECONDS); // 1秒后执行 executor.scheduleAtFixedRate(() -> System.out.println("Periodic"), 0, 2, TimeUnit.SECONDS); // 每2秒执行
(5) WorkStealingPool(工作窃取线程池,Java 8+)
- 特点:
- 基于 Fork/Join 框架(
ForkJoinPool
),每个线程有自己的任务队列,空闲线程可“窃取”其他线程的任务。 - 线程数默认等于 CPU 核心数。
- 适用场景:
- 递归、分治任务(如并行计算、树形处理)。
- 创建:
java ExecutorService executor = Executors.newWorkStealingPool();
- 注意:
- 适合任务分解,不适合 I/O 密集型任务。
(6) Custom ThreadPoolExecutor(自定义线程池)
- 特点:
- 通过
ThreadPoolExecutor
手动配置线程池参数:corePoolSize
:核心线程数。maximumPoolSize
:最大线程数。keepAliveTime
:空闲线程存活时间。workQueue
:任务队列(如LinkedBlockingQueue
、ArrayBlockingQueue
)。threadFactory
:线程创建工厂。handler
:拒绝策略(如AbortPolicy
、CallerRunsPolicy
)。
- 适用场景:
- 需精确控制线程池行为(如限制队列大小、自定义拒绝策略)。
- 创建:
java ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // corePoolSize 4, // maximumPoolSize 60, TimeUnit.SECONDS, // keepAliveTime new LinkedBlockingQueue<>(100), // workQueue Executors.defaultThreadFactory(), // threadFactory new ThreadPoolExecutor.AbortPolicy() // rejectedExecutionHandler );
2. 线程池的使用方法
以下是通过 Java 线程池执行任务的通用步骤和代码示例:
(1) 创建线程池
- 使用
Executors
工厂方法或ThreadPoolExecutor
创建。
ExecutorService executor = Executors.newFixedThreadPool(4);
(2) 提交任务
- 方式:
execute(Runnable)
:执行无返回值的任务。submit(Runnable/Callable)
:执行有返回值的任务,返回Future
。- 示例: ```java // 无返回值 executor.execute(() -> System.out.println("Task executed"));
// 有返回值
Future
(3) 管理任务
- 批量提交:
java List<Callable<String>> tasks = Arrays.asList( () -> "Task 1", () -> "Task 2" ); List<Future<String>> futures = executor.invokeAll(tasks); futures.forEach(f -> { try { System.out.println(f.get()); } catch (Exception e) { e.printStackTrace(); } });
- 定时任务(
ScheduledExecutorService
):java ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(() -> System.out.println("Periodic task"), 0, 1, TimeUnit.SECONDS);
(4) 关闭线程池
- 方式:
shutdown()
:停止接受新任务,等待现有任务完成。shutdownNow()
:立即停止,尝试中断运行任务,返回未执行任务。awaitTermination(timeout, unit)
:等待关闭完成。- 示例:
java executor.shutdown(); try { if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); }
(5) 完整示例
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
// 提交任务
for (int i = 0; i < 5; i++) {
int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " executed by " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 关闭线程池
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}
输出(示例):
Task 0 executed by pool-1-thread-1
Task 1 executed by pool-1-thread-2
Task 2 executed by pool-1-thread-1
Task 3 executed by pool-1-thread-2
Task 4 executed by pool-1-thread-1
3. 线程池参数与配置
ThreadPoolExecutor
的核心参数影响线程池行为:
- corePoolSize:
- 常驻线程数,即使空闲也保留。
- maximumPoolSize:
- 最大允许线程数,队列满时创建。
- keepAliveTime:
- 非核心线程空闲存活时间。
- workQueue:
- 任务队列类型:
LinkedBlockingQueue
:无界队列。ArrayBlockingQueue
:有界队列。SynchronousQueue
:无缓冲队列。PriorityBlockingQueue
:优先级队列。
- threadFactory:
- 自定义线程名称、优先级等。
- 示例:
java ThreadFactory factory = r -> new Thread(r, "my-thread-" + r.hashCode());
- rejectedExecutionHandler:
- 队列满且线程满时的拒绝策略:
AbortPolicy
:抛RejectedExecutionException
(默认)。CallerRunsPolicy
:调用者线程执行。DiscardPolicy
:丢弃任务。DiscardOldestPolicy
:丢弃最旧任务。
- 示例:
java ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, 4, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() );
4. 使用场景
- FixedThreadPool:
- Web 服务器处理请求,控制并发。
- CachedThreadPool:
- 短时任务(如异步日志、事件处理)。
- SingleThreadExecutor:
- 顺序任务(如数据库事务日志)。
- ScheduledThreadPool:
- 定时任务(如监控、清理)。
- WorkStealingPool:
- 并行计算(如 Fork/Join 任务)。
- Custom ThreadPoolExecutor:
- 高并发系统,需精确控制队列和拒绝策略(如电商秒杀)。
5. 注意事项
- 线程池大小:
- CPU 密集型:
核心数 + 1
(如计算任务)。 - I/O 密集型:
2 × 核心数
或更高(如网络请求)。 - 示例:4 核 CPU,计算任务用 5 线程,I/O 任务用 8-10 线程。
- 队列选择:
- 无界队列(
LinkedBlockingQueue
):小心 OOM。 - 有界队列(
ArrayBlockingQueue
):需配拒绝策略。 - 拒绝策略:
- 选择适合业务的策略,如
CallerRunsPolicy
降低速率,AbortPolicy
抛异常。 - 关闭管理:
- 总是调用
shutdown
或shutdownNow
,避免资源泄漏。 - 异常处理:
execute
不捕获异常,需在Runnable
内处理。submit
返回Future
,通过get
捕获异常。- 线程安全:
- 线程池本身线程安全,但任务逻辑需确保安全(如共享资源加锁)。
- 避免误用:
- 不要用
CachedThreadPool
处理长时任务,可能耗尽资源。 - 避免无界队列无限积压任务。
6. 面试角度
- 问“Java 线程池有哪些”:
- 提 FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledThreadPool、WorkStealingPool、ThreadPoolExecutor。
- 问“如何使用线程池”:
- 提创建(
Executors
)、提交(execute
/submit
)、关闭(shutdown
),给代码示例。 - 问“线程池参数”:
- 提 corePoolSize、maximumPoolSize、workQueue、rejectedExecutionHandler,说明作用。
- 问“场景选择”:
- 提 FixedThreadPool(稳定并发)、CachedThreadPool(短任务)、ScheduledThreadPool(定时)。
- 问“注意事项”:
- 提线程大小、队列 OOM、拒绝策略、异常处理、关闭。
- 问“自定义线程池”:
- 提
ThreadPoolExecutor
配置,举有界队列 + 拒绝策略示例。
7. 总结
- 线程池类型:
- FixedThreadPool(固定线程)、CachedThreadPool(动态线程)、SingleThreadExecutor(单线程)、ScheduledThreadPool(定时)、WorkStealingPool(Fork/Join)、ThreadPoolExecutor(自定义)。
- 使用方法:
- 创建(
Executors
或ThreadPoolExecutor
)、提交(execute
/submit
)、管理(Future
、invokeAll
)、关闭(shutdown
)。 - 场景:
- 并发控制(Fixed)、短任务(Cached)、顺序(Single)、定时(Scheduled)、并行(WorkStealing)。
- 注意:
- 配置线程数/队列、处理异常、选择拒绝策略、正确关闭。
- 面试建议:
- 提类型、代码示例(
submit
+shutdown
)、参数配置(corePoolSize
等)、场景(Web vs 定时)、注意事项(OOM、异常),清晰展示理解。
If you want to dive deeper into any part (e.g., ThreadPoolExecutor
source code, rejection policies, or thread pool tuning for specific workloads), let me know, and I can further refine the answer!