线程池的参数详细介绍 - 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 时间后被销毁。如果 allowCoreThreadTimeOuttrue,则核心线程也会被超时销毁。
  • 常见应用场景:适用于长时间没有任务的情况下,线程池会销毁空闲线程,节省资源。

示例

java

long keepAliveTime = 60; // 60秒

此示例表示线程池中超过 corePoolSize 的线程在空闲 60 秒后将被销毁。

4. unit(时间单位)

  • 类型TimeUnit
  • 说明keepAliveTime 的时间单位,可以是 TimeUnit.SECONDSTimeUnit.MILLISECONDSTimeUnit.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-0Custom-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-0Custom-Thread-1 等。
  • RejectedExecutionHandler 设置为 CallerRunsPolicy,当线程池不能处理任务时,任务会由提交任务的线程来执行。

线程池工作流程

  1. 任务提交:当任务提交给线程池时,线程池会先检查是否有空闲线程。如果没有,且线程池中的线程数小于 corePoolSize,会创建新的线程执行任务。
  2. 任务排队:当线程池中的线程数已经达到 corePoolSize,但还没有达到 maximumPoolSize 时,新的任务会被放入 workQueue 队列中。
  3. 线程扩展:如果任务队列已满,且线程池中的线程数小于 maximumPoolSize,线程池会创建新的线程来处理任务。
  4. 任务拒绝:如果线程池中的线程数已达到 maximumPoolSize 且任务队列也已满,任务将根据 RejectedExecutionHandler 策略来处理。

通过合理的配置线程池参数,可以确保系统在高并发场景下平稳运行,避免线程过多导致的资源浪费或线程过少导致的任务阻塞。

Java碎碎念 文章被收录于专栏

来一杯咖啡,聊聊Java的碎碎念呀

全部评论

相关推荐

评论
3
2
分享

创作者周榜

更多
牛客网
牛客企业服务