springboot中的线程池的配置

本文大部分理论文档转自 https://blog.csdn.net/zhouhl_cn/article/details/7392607

大神们多分享,我们才能进步;

最近在使用JAVA 的JHIPSTER的框架,其中对于多线程的操作比较懵,搜了点资料.自己也记录下,加深学习;

配置文件中给的是一个连接,然后去找连接看说明,其实也没什么东西.下图

springboot中的线程池的配置_第1张图片

github上的给的说明是这样的

springboot中的线程池的配置_第2张图片

 

对于大佬来说,这些文档就足够了.但是菜鸡的我,还是不懂.....

springboot使用的多线程的config类为

package com.trs.idap.config;

import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
import io.github.jhipster.config.JHipsterProperties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {

    private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);

    private final JHipsterProperties jHipsterProperties;

    public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
        this.jHipsterProperties = jHipsterProperties;
    }

    @Override
    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        log.debug("Creating Async Task Executor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
        executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
        executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
        executor.setThreadNamePrefix("analysis-Executor-");
        return new ExceptionHandlingAsyncTaskExecutor(executor);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

 

配置类只是设置了这三个参数的值;;

 

线程池的实现是ThreadPoolExecutor...

ThreadPoolExecutor类可以设置的参数主要有:

就是上面的几个:

corePoolSize:核心线程数,核心线程会一直存活,即使没有任务需要处理.当线程数小于核心线程数时,即使现有的线程空闲,线程池也会优先创建新线程来处理任务,而不是直接交给现有的线程处理;核心线程在allowCoreThreadTimeout被设置为true时会超时退出,默认情况下不会退出..

maxPoolSize 当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize.如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常;

keepAliveTime 当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize,如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0.

 

allowCoreThreadTimeout 是否允许核心线程空闲退出,默认值为false.一般就使用false的

 

queueCapacity  任务队列容量.从maxPoolSize的描述上可以看出,任务队列的容量会影响到线程的变化,因此任务队列的长度也需要恰当的设置.我们中给了10000,相当于就是没有上限了....

 

即线程池的执行原则大概为:

  1. 当线程数小于核心线程数时,创建线程.
  2. 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列;
  3. 当线程数大于等于核心线程数,且任务队列已满.
    1. 若线程数小于最大线程数,创建线程;
    2. 若线程数等于最大线程数,抛出异常,拒绝任务;

 

系统负载

参数的设置跟系统的负载有直接的关系,系统负载的相关参数:

  • tasks 每秒需要处理的最大任务数量
  • tasktime 处理第n个任务所需要的时间
  • responsetime 系统允许任务最大的响应时间,比如每个任务的响应时间不得超过2秒.

 

系统参数配置与线程数关系

corePoolSize 每个任务需要tasktime秒处理,则每个线程每秒可处理1/tasktime个任务.系统每秒有tasks个任务要处理,则需要的线程数为tasks/(1/tasktime),即 tasks*tasktime个线程数.假设系统每秒任务量为100-1000,每个任务耗时0.1s,则需要100-0.1到1000*0.1,即10-100个线程.那么corePoolSize应该设置为大于10,具体数字最好根据8020原则,即80%情况下系统每秒任务数,若系统80%的情况下任务数小于200,最多时为1000,则corePoolSize可设置为20;

queueCapacity 任务队列的长度要根据核心线程数,以及系统对任务响应时间的要求有关.队列长度可以设置为(corePoolSize/tasktime)*responsetime:(20/0.1)*2=400;即队列长度可设置为400;

队列长度设置过大,会导致任务响应时间过长.切记一下写法:

LinkedBlockingQueue queue = new LinkedBlockingQueue();

这实际就是将队列长度设置为Integer.MAX_VALUE.将会导致线程数量永远为corePoolSize,再也不会增加,当任务数量陡增时,任务响应时间也将随之陡增;

好像我的问题就出现在这里,这里先挖个坑!!!!

从上文可以看到,我们的queue是10000;吓人的....

 

maxPoolSize 当系统负载大道最大值时,核心线程数已无法按时处理完所有任务,这是就需要增加线程.每秒200个任务需要20个线程,那么当每秒1000个任务时,则需要(1000-queueCapacity)*(20/200),即60个线程,可将maxPoolSize设置为60;

 

keepAliveTime: 线程数量只增加不减少也不行.当负载降低时,可减少线程数量,如果一个线程空闲时间达到keepAliveTime,该线程就退出.默认情况下线程池最少会保持corePoolSize个线程;

 

allowCoreThreadTimeout 默认情况下核心线程不会退出,可通过将该参数设置为true,让核心线程也退出.

 

如上计算,并没有考虑cpu的情况.若结合cpu的情况,比如,当线程数量达到50时,cpu达到100%,则将maxPoolSize设置为60也不合适,此时若系统负载长时间维持在每秒1000个任务,则超出线程池处理能力,应设法降低每个任务的处理时间(tasktime).

写的真棒....

 

 

 

 

你可能感兴趣的:(多线程,微服务)