在创建和配置线程池时,有几个核心参数是需要仔细设置的,以确保线程池能够高效地处理任务并适应系统负载。以下是线程池的核心参数及其作用:
1. 核心线程数 (corePoolSize)
定义: 线程池中保持活动的最小线程数。
作用: 即使没有任务,核心线程也会保持存活。这有助于处理高负载情况下的任务。
2. 最大线程数 (maximumPoolSize)
定义: 线程池中允许的最大线程数。
作用: 当核心线程数不够处理任务时,线程池会创建更多的线程,直到达到最大线程数。超过这个数量的任务会被拒绝或等待。
3. 空闲线程存活时间 (keepAliveTime)
定义: 当线程池中的线程数超过核心线程数时,线程在空闲时保持的最长时间。
作用: 当线程数超过核心线程数,并且这些线程在指定时间内没有执行任务,它们会被终止,以节省系统资源。
4. 时间单位 (unit)
定义: keepAliveTime 参数的时间单位(如秒、毫秒等)。
作用: 指定 keepAliveTime 参数的时间单位,以正确管理线程的空闲时间。
5. 任务队列 (workQueue)
定义: 用于保存等待执行任务的队列。
作用: 线程池中的任务会被放入这个队列中,等待线程池中的线程处理。常见的队列类型包括:
有界队列(如 ArrayBlockingQueue):限制队列的大小,防止无限制地积压任务。
无界队列(如 LinkedBlockingQueue):没有限制队列的大小,可以存放无限数量的任务。
优先级队列(如 PriorityBlockingQueue):可以根据任务的优先级来处理任务。
6. 线程工厂 (threadFactory)
定义: 用于创建新线程的工厂类。
作用: 线程池使用这个工厂来创建新线程,可以自定义线程的名称、优先级等属性。
7. 拒绝策略 (handler)
定义: 当线程池无法处理新任务时的策略。
作用: 确定如何处理任务队列满、线程池已达到最大线程数等情况。常见的拒绝策略包括:
AbortPolicy: 抛出 RejectedExecutionException 异常。
CallerRunsPolicy: 在调用线程中运行任务。
DiscardPolicy: 丢弃任务,不抛出异常。
DiscardOldestPolicy: 丢弃最旧的任务,然后重试提交新任务。
示例代码
以下是使用 Java ThreadPoolExecutor 类创建线程池的一个简单示例:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // corePoolSize
10, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS, // unit for keepAliveTime
new LinkedBlockingQueue<>(), // workQueue
new ThreadPoolExecutor.CallerRunsPolicy() // handler
);
// 提交任务
for (int i = 0; i < 20; i++) {
executor.submit(() -> {
try {
Thread.sleep(1000); // 模拟任务执行
System.out.println("Task executed by " + Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 关闭线程池
executor.shutdown();
}
}
在这个示例中,线程池有 4 个核心线程,最大线程数为 10,空闲线程的存活时间为 60 秒,使用了一个 LinkedBlockingQueue 作为任务队列,任务会被提交到调用线程中执行(如果线程池满)。