ThreadPoolExecutor
是 Java 提供的一个强大的线程池实现类,它允许我们灵活地配置和管理线程池的各种参数。ThreadPoolExecutor
可以通过设置核心线程数、最大线程数、线程存活时间、任务队列和拒绝策略等,满足不同场景下的并发需求。
1. ThreadPoolExecutor
构造函数
ThreadPoolExecutor
的构造函数如下:
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 非核心线程的存活时间
TimeUnit unit, // 存活时间的单位
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
2. 关键参数
- corePoolSize:核心线程数,始终保持在线的线程数量,即使这些线程处于空闲状态。
- maximumPoolSize:最大线程数,当任务队列已满且正在运行的线程数量小于最大线程数时,会创建新的线程来执行任务。
- keepAliveTime:当线程数超过核心线程数时,多余的空闲线程存活的最长时间。超过这个时间后,多余的线程会被终止。
- unit:
keepAliveTime
的时间单位。 - workQueue:用于存放等待执行任务的队列。
- threadFactory:用于创建新线程的工厂类,可以用来为每个创建的线程设置名称和优先级等属性。
- handler:拒绝策略,当任务无法提交到线程池时(任务队列已满且线程数达到最大值),会执行该策略。
3. 示例代码
下面是一个使用 ThreadPoolExecutor
的示例:
import java.util.concurrent.*;
public class ThreadPoolExecutorDemo {
public static void main(String[] args) {
// 创建任务队列
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(10);
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // 核心线程数
4, // 最大线程数
60, // 线程存活时间
TimeUnit.SECONDS, // 时间单位
workQueue, // 任务队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
// 提交任务
for (int i = 0; i < 20; i++) {
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " is executing task.");
try {
Thread.sleep(2000); // 模拟任务执行时间
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 关闭线程池
executor.shutdown();
}
}
4. 拒绝策略
ThreadPoolExecutor
提供了几种内置的拒绝策略,可以在任务无法执行时采用:
- AbortPolicy:默认策略,直接抛出
RejectedExecutionException
。 - CallerRunsPolicy:调用执行自己的
execute
方法运行任务,即由调用者所在的线程来运行这个任务。 - DiscardPolicy:直接丢弃任务,不抛出异常。
- DiscardOldestPolicy:丢弃最老的一个任务,然后尝试重新提交当前任务。
可以通过实现 RejectedExecutionHandler
接口来自定义拒绝策略:
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// 自定义处理逻辑
System.out.println("Task rejected: " + r.toString());
}
}
5. 自定义线程工厂
通过实现 ThreadFactory
接口,可以自定义线程的创建过程:
public class CustomThreadFactory implements ThreadFactory {
private int threadId;
private String name;
public CustomThreadFactory(String name) {
threadId = 1;
this.name = name;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, name + "-Thread-" + threadId);
System.out.println("Created new thread with id: " + threadId + " and name: " + t.getName());
threadId++;
return t;
}
}
// 使用自定义线程工厂
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10),
new CustomThreadFactory("CustomThreadFactory"),
new ThreadPoolExecutor.AbortPolicy()
);
6. 生命周期管理
ThreadPoolExecutor
提供了以下方法来管理线程池的生命周期:
- shutdown():平滑关闭线程池,已提交的任务会继续执行,但不会接受新任务。
- shutdownNow():立即关闭线程池,试图中断正在执行的任务,并返回未执行的任务列表。
- isShutdown():判断线程池是否已关闭。
- isTerminated():判断所有任务是否已完成。
- awaitTermination(long timeout, TimeUnit unit):等待线程池在指定时间内关闭。
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
总结
ThreadPoolExecutor
提供了丰富的配置选项,可以根据具体需求灵活地配置线程池的行为和策略。通过合理地使用线程池,可以显著提高应用程序的并发性能和资源利用率。