springboot项目搭建1000-配置线程池

资源贴:

ThreadPoolTaskExecutor的配置:https://www.cnblogs.com/lic309/p/4186880.html

ThreadPoolTaskExecutor的架构:https://blog.csdn.net/f641385712/article/details/80832636

拒绝策略:http://blog.sina.com.cn/s/blog_714cb3040102wc6i.html

等待线程执行完毕,在执行主线程:http://www.importnew.com/21889.html

项目地址:https://github.com/wenrongyao/springboot-demo.git

摘要:配置线程池

 1、新建线程池配置类,注意这边的启动类是在group id(maven坐标)下,可以直接扫到这个类,如果启动类不在group id下需要在启动类中通过@ImportAutoConfiguration引入。

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created by rongyaowen
 * on 2019/1/4.
 */
@Configuration
@EnableAsync
public class TaskExecutorConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 最先线程池,低于这个数,新建线程
        threadPoolTaskExecutor.setCorePoolSize(10);
        // 最大线程池
        threadPoolTaskExecutor.setMaxPoolSize(15);
        // 任务队列
        threadPoolTaskExecutor.setQueueCapacity(30);
        // 任务执行策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

2、异步方法执行类

这边为了演示另起了一个包async,实际开发中通常是在service层

@Async写在方法上表示方法异步,写在类上表示所有方法都是异步的。

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * Created by rongyaowen
 * on 2019/1/4.
 */
@Component
public class AsyncDemo {

    @Async
    public void test(int i) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(i + "异步线程id:" + Thread.currentThread().getId());
    }
}

3、ThreadPoolTaskExecutor的常用配置

corePoolSize:线程池维护线程的最小数量. 

maxPoolSize:线程池维护线程的最大数量. 

keepAliveSeconds:空闲线程的存活时间. 

queueCapacity:持有等待执行的任务队列. 

rejectedExecutionHandler: 

用来拒绝一个任务的执行,有两种情况会发生这种情况。 

  一是在execute方法中若addIfUnderMaximumPoolSize(command)为false,即线程池已经饱和; 

  二是在execute方法中, 发现runState!=RUNNING || poolSize == 0,即已经shutdown,就调用ensureQueuedTaskHandled(Runnable command)

 

拒绝策略:

 

Reject策略预定义有四种: 

(1)ThreadPoolExecutor.AbortPolicy策略,是默认的策略,处理程序遭到拒绝将抛出运行时 RejectedExecutionException。 

(2)ThreadPoolExecutor.CallerRunsPolicy策略 ,只要线程池未关闭,该策略直接在调用者线程中运行当前被丢弃的任务。显然这样不会真的丢弃任务,但是,调用者线程性能可能急剧下降。

(3)ThreadPoolExecutor.DiscardPolicy策略,不能执行的任务将被丢弃(会丢失任务). 

(4)ThreadPoolExecutor.DiscardOldestPolicy策略,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程,会丢失任务).

执行顺序:

当一个任务通过 execute(Runnable) 方法欲添加到线程池时,线程池采用的策略如下(即添加任务的策略):

如果此时线程池中的数量小于 corePoolSize ,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。

如果此时线程池中的数量等于 corePoolSize ,但是缓冲队列 queueCapacity未满,那么任务被放入缓冲队列。

如果此时线程池中的数量大于 corePoolSize ,缓冲队列 queueCapacity满,并且线程池中的数量小于maxPoolSize ,建新的线程来处理被添加的任务。

如果此时线程池中的数量大于 corePoolSize ,缓冲队列 queueCapacity满,并且线程池中的数量等于maxPoolSize ,那么通过 handler 所指定的策略来处理此任务。

任务处理的优先级(顺序)为:

核心线程 corePoolSize 、任务队列 queueCapacity、最大线程 maxPoolSize ,如果三者都满了,使用 handler处理被拒绝的任务。当线程池中的线程数量大于 corePoolSize 时,如果某线程空闲时间超过 keepAliveTime ,线程将被终止。这样,线程池可以动态的调整池中的线程数。

ThreadPoolTaskExecutor的默认配置

springboot项目搭建1000-配置线程池_第1张图片

核心线程为1,最大线程和最大队列都是最大整数。所以如果没有配置自己的Executor,即没有TaskExecutorConfig类,只是在启动类上通过@EnableAsync开启异步支持,那么通过@Async配置的方法每次会开启一个新的线程,使用默认配置,这种线程池就是个空壳子,没有什么意义。

4、总结

综上,如果项目中开启线程池任务个数是固定的,那么可以通过配置corePoolSize,maxPoolSize,queueCapacity三个参数来调整,如果参数不定,可以只配置corePoolSize,maxPoolSize参数,queueCapacity使用默认值,即最大,但是这种做法有个问题即使任务堆积。

 

你可能感兴趣的:(#,Spring,Boot项目搭建)