线程池在Java中通常使用java.util.concurrent.ThreadPoolExecutor
类来实现,它有七个核心参数,这些参数用于配置线程池的行为:
-
corePoolSize:
- 线程池的基本大小,即线程池中的核心线程数。即使核心线程无任务执行,也不会被回收,除非设置了allowCoreThreadTimeOut为true。
-
maximumPoolSize:
- 线程池所能容纳的最大线程数。当核心线程数已满且工作队列也已满时,线程池会创建新的线程来处理任务,直至达到最大线程数。
-
keepAliveTime:
- 非核心线程闲置超时时长。如果当前线程数超过核心线程数,那么在超过指定时间后,闲置线程会被终止,直到线程池大小回到corePoolSize。
-
unit:
- 上述keepAliveTime参数的时间单位,例如 TimeUnit.SECONDS、TimeUnit.MILLISECONDS等。
-
workQueue:
- 工作队列,线程池使用阻塞队列来暂存待处理的任务。可以选择的队列类型有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。
-
threadFactory:
- 线程工厂,用于创建新线程。可以通过定制线程工厂为新建的线程设置名称、优先级等属性。
-
handler:
- 拒绝策略,当线程池和工作队列均满,无法接受新任务时,定义如何处理新提交的任务。线程池提供了四种拒绝策略:
- AbortPolicy(默认):抛出RejectedExecutionException异常,阻止系统正常运行。
- CallerRunsPolicy:调用者所在的线程自己来执行任务,这种方式提供了一种简单的反馈控制机制,将任务回退到调用者,从而降低新任务的流量。
- DiscardPolicy:默默地丢弃新任务,不予处理。
- DiscardOldestPolicy:丢弃队列中最旧的未处理任务,然后尝试重新提交当前任务。
- 拒绝策略,当线程池和工作队列均满,无法接受新任务时,定义如何处理新提交的任务。线程池提供了四种拒绝策略:
四个拒绝策略指的是上述提到的handler
参数可以选择的四种策略。在创建线程池时,通过构造函数传入适当的参数来配置这些策略,以适应不同场景下的任务调度需求。
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 定义线程池核心参数
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
// 创建四种拒绝策略实例
RejectedExecutionHandler rejectionHandlers[] = {
new ThreadPoolExecutor.AbortPolicy(), // 默认策略,抛出RejectedExecutionException异常
new ThreadPoolExecutor.CallerRunsPolicy(), // 调用者线程执行任务
new ThreadPoolExecutor.DiscardPolicy(), // 直接丢弃任务,不抛出异常
new ThreadPoolExecutor.DiscardOldestPolicy() // 丢弃队列中最旧的任务,尝试执行当前任务
};
// 分别使用四种拒绝策略创建并测试线程池
for (RejectedExecutionHandler rejectionHandler : rejectionHandlers) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
Executors.defaultThreadFactory(),
rejectionHandler
);
for (int i = 0; i < 200; i++) { // 提交200个任务
final int taskId = i;
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() + " is processing task " + taskId);
try {
Thread.sleep(100); // 模拟耗时任务
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
executor.shutdown();
while (!executor.isTerminated()) {
// 等待所有任务完成
}
System.out.println("\n---------- 使用 " + rejectionHandler.getClass().getSimpleName() + " 策略 ----------\n");
}
}
}