线程池的参数详细介绍 - Java
线程池(Thread Pool)是为了解决频繁创建和销毁线程所带来的性能问题而提出的一种线程管理机制。使用线程池可以重复利用已创建的线程,减少线程创建和销毁的开销,并且能有效控制系统中线程的数量,防止线程过多导致资源耗尽。
线程池在 Java 中是通过 ThreadPoolExecutor
实现的,下面我将详细介绍 ThreadPoolExecutor
的各个参数,并给出具体的示例。
ThreadPoolExecutor
构造函数
ThreadPoolExecutor
的构造函数如下:
java ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
各个参数的详细介绍与示例:
1. corePoolSize(核心池大小)
- 类型:
int
- 说明:线程池中始终保留的线程数,线程池中的线程数不会少于
corePoolSize
,即使这些线程处于空闲状态。核心线程即使没有任务执行,也会被保持。 - 常见应用场景:如果任务执行频繁,且负载较高,可以设置较大的核心线程数,以减少线程的创建和销毁成本。
示例:
java int corePoolSize = 4;
此示例表示线程池中的核心线程数为 4,即线程池至少会有 4 个线程在空闲时保持活跃。
2. maximumPoolSize(最大池大小)
- 类型:
int
- 说明:线程池中允许的最大线程数。当线程池中已有
corePoolSize
个线程且任务队列已满时,如果新任务提交,线程池会创建新的线程,直到线程池中的线程数达到maximumPoolSize
。 - 常见应用场景:可以根据系统资源配置该值,通常在任务量很大且负载较高时,设置较大的
maximumPoolSize
。
示例:
java int maximumPoolSize = 10;
此示例表示线程池中最多可以有 10 个线程。
3. keepAliveTime(空闲线程存活时间)
- 类型:
long
- 说明:当线程池中的线程数超过
corePoolSize
时,多余的线程将在空闲keepAliveTime
时间后被销毁。如果allowCoreThreadTimeOut
为true
,则核心线程也会被超时销毁。 - 常见应用场景:适用于长时间没有任务的情况下,线程池会销毁空闲线程,节省资源。
示例:
java long keepAliveTime = 60; // 60秒
此示例表示线程池中超过 corePoolSize
的线程在空闲 60 秒后将被销毁。
4. unit(时间单位)
- 类型:
TimeUnit
- 说明:
keepAliveTime
的时间单位,可以是TimeUnit.SECONDS
、TimeUnit.MILLISECONDS
、TimeUnit.MINUTES
等。 - 常见应用场景:根据
keepAliveTime
的值选择适合的时间单位。
示例:
java TimeUnit unit = TimeUnit.SECONDS;
此示例表示 keepAliveTime
使用秒为单位。
5. workQueue(任务队列)
- 类型:
BlockingQueue<Runnable>
- 说明:用于存放等待执行的任务。常见的实现有:LinkedBlockingQueue:无界队列,大小为 Integer.MAX_VALUE,适用于任务量无法预测的场景。ArrayBlockingQueue:有界队列,适用于任务量可以预估的场景。SynchronousQueue:没有容量的队列,每个提交的任务都必须等待一个线程来处理,适用于需要处理每个任务的特殊场景。
示例:
java BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
此示例表示线程池的任务队列大小为 100,当队列满时,新的任务会被拒绝。
6. ThreadFactory
- 类型:
ThreadFactory
- 说明:线程池用来创建新线程的工厂。通过自定义
ThreadFactory
,你可以设置线程的名字、优先级等属性。默认的ThreadFactory
会创建普通的线程。 - 常见应用场景:如果你需要给线程命名或设置特定的线程属性,可以自定义
ThreadFactory
。
示例:
java ThreadFactory threadFactory = new ThreadFactory() { private int count = 0; public Thread newThread(Runnable r) { return new Thread(r, "Custom-Thread-" + count++); } };
此示例自定义了线程工厂,每个线程的名字都会被设置为 Custom-Thread-0
、Custom-Thread-1
等。
7. RejectedExecutionHandler
- 类型:
RejectedExecutionHandler
- 说明:当线程池无法处理新任务时,执行的策略。常见的拒绝策略有:AbortPolicy:默认策略,抛出 RejectedExecutionException。CallerRunsPolicy:由提交任务的线程执行该任务。DiscardPolicy:丢弃任务。DiscardOldestPolicy:丢弃队列中最旧的任务。
示例:
java RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
此示例使用 CallerRunsPolicy
策略,如果线程池无法处理新任务,任务将由提交任务的线程来执行。
完整示例
java 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 new LinkedBlockingQueue<>(100), // workQueue new ThreadFactory() { private int count = 0; @Override public Thread newThread(Runnable r) { return new Thread(r, "Custom-Thread-" + count++); } }, new ThreadPoolExecutor.CallerRunsPolicy() // RejectedExecutionHandler ); // 提交任务到线程池 for (int i = 0; i < 200; i++) { executor.submit(() -> { System.out.println(Thread.currentThread().getName() + " is executing the task."); try { Thread.sleep(1000); // 模拟任务执行 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } // 关闭线程池 executor.shutdown(); } }
解释:
- corePoolSize 为 4,表示线程池有 4 个核心线程。
- maximumPoolSize 为 10,最多允许 10 个线程。
- keepAliveTime 为 60 秒,超过 4 个线程后的线程将在空闲 60 秒后被销毁。
- workQueue 使用一个
LinkedBlockingQueue
,最大容量为 100。当任务超过 100 个时,新的任务会被拒绝。 - ThreadFactory 自定义了线程的名字为
Custom-Thread-0
,Custom-Thread-1
等。 - RejectedExecutionHandler 设置为
CallerRunsPolicy
,当线程池不能处理任务时,任务会由提交任务的线程来执行。
线程池工作流程
- 任务提交:当任务提交给线程池时,线程池会先检查是否有空闲线程。如果没有,且线程池中的线程数小于
corePoolSize
,会创建新的线程执行任务。 - 任务排队:当线程池中的线程数已经达到
corePoolSize
,但还没有达到maximumPoolSize
时,新的任务会被放入workQueue
队列中。 - 线程扩展:如果任务队列已满,且线程池中的线程数小于
maximumPoolSize
,线程池会创建新的线程来处理任务。 - 任务拒绝:如果线程池中的线程数已达到
maximumPoolSize
且任务队列也已满,任务将根据RejectedExecutionHandler
策略来处理。
通过合理的配置线程池参数,可以确保系统在高并发场景下平稳运行,避免线程过多导致的资源浪费或线程过少导致的任务阻塞。
Java碎碎念 文章被收录于专栏
来一杯咖啡,聊聊Java的碎碎念呀