线程池核心参数配置及动态调节

线程池的基本认识以及使用示例:https://blog.csdn.net/weixin_39439156/article/details/135099731
在实际生产中我们用线程池的难点很多时候实在配置核心参数时,因为很多时候我们也无法预计生产环境的一个使用情况,可能和我们预估情况有所差别,这时候可能我们就会去动态的去调整我们的核心参数。下面还是先简单介绍一下核心参数,再提供一个动态修改参数的demo。

1. 线程池的核心参数配置

1.1 核心参数

线程池的核心参数包括: 核心线程数(corePoolSize)、最大线程数(maximumPoolSize)、任务队列(workQueue)、线程存活时间(keepAliveTime):

1.2 工作原理

当有任务提交给线程池时,线程池会按照以下规则执行任务:

  1. 如果核心线程数尚未达到上限,线程池会创建一个新的核心线程来执行任务。
  2. 如果核心线程数已满,但是线程池中的线程总数(包括核心线程和非核心线程)未达到最大线程数,线程池会创建一个新的非核心线程来执行任务。
  3. 如果线程池中的线程总数已达到最大线程数,并且任务队列未满,线程池会将任务放入任务队列中等待执行。
  4. 如果线程池中的线程总数已达到最大线程数,并且任务队列已满,线程池会根据拒绝策略(RejectedExecutionHandler)来处理无法执行的任务。

当线程池中的线程空闲一段时间后,根据线程存活时间的设置,非核心线程可能会被销毁,以减少资源消耗。

1.3 线程池的配置思路

合理配置线程池参数对于获得最佳性能和资源利用至关重要。以下是一些常用的线程池配置建议:

  • 核心线程数应根据系统的负载和并发需求进行调整。如果系统需要处理较大的并发任务,可以增加核心线程数以提高响应性能。
  • 最大线程数应根据系统资源和并发负载进行调整。过多的线程数可能会浪费资源,而过少的线程数可能会导致任务排队等待执行。
  • 任务队列的选择应根据具体需求来决定。如果系统需要支持大量的并发任务,可以选择无界队列来避免任务被拒绝执行。如果系统资源有限,可以选择有界队列来控制任务的数量。
  • 线程存活时间应根据任务执行时间和系统负载进行调整。如果任务执行时间较长,可以增加线程存活时间以避免频繁地创建和销毁线程。

1.3 通过apollo动态配置线程池核心参数

在无法预估线上环境的情况、或者线上环境变化巨大的情况下,我们可以通过ThreadPoolExecutor 提供的set方法对其核心参数进行动态调整。

  • 初始化线程池
	
  /**
   * coreSize、maxPoolSize、aliveSeconds 均通过apollo配置
   * @return
   */
  @Bean("mePoolExecutor")
  public ThreadPoolExecutor poolExecutor(){
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(coreSize,
        maxPoolSize,
        aliveSeconds,
        TimeUnit.SECONDS,
        new ArrayBlockingQueue<>(100));
    return poolExecutor;
  }
  • 监听线程池的相关核心参数是否变化,变化则重新set

实现ConfigChangeListener,ApplicationListener监听ApolloConfigChangeEvent事件,判断是否核心配置参数发生变化,如果是则重新set更新。

public class ListenerApollo implements ConfigChangeListener, ApplicationListener<ApolloConfigChangeEvent> {
  @Override
  public void onChange(ConfigChangeEvent configChangeEvent) {
    //核心线程配置发生变化、重新set
    ConfigChange coreSize = configChangeEvent.getChange("corSize");
    if( coreSize!= null){
      ThreadPoolExecutor executor = SpringUtil.getBean(ThreadPoolExecutor.class);
      executor.setCorePoolSize(Integer.valueOf(coreSize.getNewValue()));
    }
    //最大线程、线程存活时间 配置发生变化、重新set todo 同上
    
  }

  @Override
  public void onApplicationEvent(ApolloConfigChangeEvent event) {
    this.onChange(event.getConfigChangeEvent());
  }
}
  • 注册listener
    最后将Listener注册到我们的应用中,我这边利用springbootSPI的机制,将其注册
    在resource下面新建META-INFO\spring.factories文件,文件内容:
    org.springframework.context.ApplicationListener=
    com.zgph.employment.core.ListenerApollo

到这里就可以动态的去调成线程池相关的核心参数了

你可能感兴趣的:(java,数据库,前端)