十二、连接池线程池配置——线程池

十二、连接池线程池配置——线程池

线程池是为了提高系统性能而设计的,通过减少线程的创建和销毁次数,降低了系统资源的消耗。线程池能够有效地限制并发线程的数量,防止因线程过多而导致的系统崩溃。

在这里插入图片描述

1. 线程池的基本概念

每个线程都需要一个内存栈来存储局部变量和操作栈等信息。可以通过 -Xss 参数调整每个线程的栈大小(64位系统默认 1024KB,建议根据实际需求调整,如 256KB),以便创建更多的线程。

然而,JVM 并不会无限制地创建线程,因此使用线程池可以限制线程的数量,从而保护系统的稳定性。线程池通常配合队列使用,以限制并发处理任务的数量。当任务数量超过队列容量时,可以通过拒绝策略来处理,从而保护系统免受过多请求的冲击。

2. 线程池的主要配置参数

2.1 主要配置参数
  • corePoolSize:核心线程池大小,指在没有任务处理时线程池中保持的最小线程数。即使线程池中的任务已经完成,核心线程也会被保留,以便快速处理未来的任务。

  • maximumPoolSize:线程池最大线程数,指在任务量非常大时线程池中允许创建的最大线程数量。当任务数超过核心线程数且任务队列满时,线程池将创建新的线程,直到达到最大线程数。

  • keepAliveTime:线程池中线程的最大空闲时间。超过此时间的线程会被回收,以释放资源。如果线程池中的线程数超过核心线程数且线程处于空闲状态超过 keepAliveTime,这些线程将被终止,线程池会缩小到核心线程数大小。

  • workQueue:线程池使用的任务缓冲队列,用于存放等待执行的任务。常见类型包括:

    • 有界阻塞数组队列 ArrayBlockingQueue:固定大小的队列,任务满时会阻塞添加任务的线程。
    • 有界/无界阻塞链表队列 LinkedBlockingQueue:链表结构的队列,支持有界和无界,通常用于生产者-消费者场景。
    • 优先级阻塞队列 PriorityBlockingQueue:支持任务优先级的队列,任务按优先级顺序处理。
    • 无缓冲区阻塞队列 SynchronousQueue:不存储任务的队列,提交任务时需要有线程立即处理,常用于任务立即执行的场景。
  • threadFactory:用于创建线程的工厂,可以自定义线程的名称、是否为后台线程等属性。通过实现 ThreadFactory 接口,可以创建具有特定属性的线程。

  • rejectedExecutionHandler:当任务队列满且线程池的线程数已达到最大线程数时,线程池的拒绝策略用于处理无法执行的任务。包括:

    • AbortPolicy:直接抛出 RejectedExecutionException 异常,表明任务无法被接受。
    • DiscardPolicy:丢弃无法执行的任务,不抛出异常。
    • DiscardOldestPolicy:丢弃最旧的任务,将新的任务添加到队列中。
    • CallerRunsPolicy:由主线程执行无法被接受的任务,减少任务提交速率。
2.2 主要配置参数示例

下面是一个基于 ThreadPoolExecutor 的线程池配置示例,演示如何设置主要的线程池参数:

import java.util.concurrent.*;

public class ThreadPoolConfig {
   

    public static ExecutorService createThreadPool() {
   
        // 创建线程池
        return new ThreadPoolExecutor(
            10, // corePoolSize: 核心线程池大小
            50, // maximumPoolSize: 线程池最大线程数
            60L, // keepAliveTime: 线程的最大空闲时间
            TimeUnit.SECONDS, // keepAliveTime 的时间单位
            new LinkedBlockingQueue<>(100), // workQueue: 任务队列,使用有界阻塞链表队列
            new ThreadFactory() {
    // threadFactory: 创建线程的工厂
                @Override
                public Thread newThread(Runnable r) {
   
                    return new Thread(r, "CustomThread"); // 设置线程名称
                }
            },
            new ThreadPoolExecutor.AbortPolicy() // rejectedExecutionHandler: 拒绝策略,直接抛出异常
        );
    }

    public static void main(String[] args) {
   
        ExecutorService executorService = createThreadPool();
        
        // 提交测试任务
        for (int i = 0; i < 120; i++) {
   
            final int taskId = i;
            executorService.submit(() -> {
   
                System.out.println("Task " + taskId + " is being executed by " + Thread.currentThread().getName());
                try {
   
                    Thread.sleep(1000); // 模拟任务处理
                } catch (InterruptedException e) {
   
                    Thread.currentThread().interrupt();
                }
            });
        }
        
        // 关闭线程池
        executorService.shutdown();
    }
}

运行示例:

在这里插入图片描述

配置说明:

  1. corePoolSize:设置为 10,表示线程池中至少保留 10 个核心线程,即使这些线程没有任务时也不会被回收。

  2. maximumPoolSize:设置为 50,表示线程池中允许最多创建 50 个线程来处理任务。

  3. keepAliveTime:设置为 60L,表示线程空闲时间达到 60 秒后将被回收。时间单位为 TimeUnit.SECONDS

  4. workQueue:使用 LinkedBlockingQueue 类型的任务队列,大小设置为 100。如果线程池中的线程数量达到核心线程数,任务将被放入队列中等待执行。

  5. threadFactory:自定义 ThreadFactory,创建线程时设置线程名称为 "CustomThread"。可以帮助更好地识别线程。

  6. rejectedExecutionHandler:使用 AbortPolicy 拒绝策略。当任务队列满且线程池中线程数已达到最大线程数时,直接抛出 RejectedExecutionException 异常。

3. 线程池的实现

Java 提供了 ExecutorService 的几种主要实现,用于满足不同的任务处理需求:

  • ThreadPoolExecutor:标准线程池实现,提供了高度的配置灵活性。
  • ScheduledThreadPoolExecutor:支持延迟和定期执行任务的线程池。
  • ForkJoinPool:使用 work-stealing 模式的线程池,适用于需要处理大量小任务的场景。
3.1 创建线程池

不同类型的线程池可以通过 Executors 工厂方法来创建,以下是常用的几种线程池及其等价实现方式:

  1. 单线程池

    单线程池始终使用一个工作线程来执行任务,保证任务按顺序执行。

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    

    等价于:

    return new FinalizableDelegatedExecutorService(
        new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
    );
    
  2. 固定数量线程池

    固定数量线程池始终使用固定数量的线程来执行任务,适用于任务负载固定的情况。

    ExecutorService executorService = Executors.newFixedThreadPool(10);
    

    等价于:

    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    
  3. 可缓存线程池

    可缓存线程池会根据需要创建新线程,并缓存空闲线程,适用于任务量动态变化的情况。

    ExecutorService executorService = Executors.newCachedThreadPool();
    

    等价于:

    return new ThreadPoolExecutor
  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆萌宝儿姐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值