SpringBoot 线程池

476 阅读2分钟

SpringBoot 线程池定义:

相信看这篇文章的人对线程池有一定了解了,在日常生产工作中会根据不同的业务场景定义线程池,每次得考虑线程池定义是单利的并且根据不同的业务场景定义线程池:核心线程数、最大线程数、队列长度、线程池名称、拒绝策略等参数可以通过SpringBoot 自动装配的方式定义。

注意事项

  1. Spring线程池初始化一定要调用initialize方法
  2. 指定多个线程池一定指定beanName 否则会默认使用一个线程池
  3. 开启异步调用注解@EnableAsync
  4. 在方法上指定注解@Async,并指定线程池名称

Properties定义

package com.org.drango.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池装配置文件类
 *
 * @author sino
 */
@Data
@ConfigurationProperties(prefix = "spring.pool")
public class ThreadPoolExecutorProperties {
    /**
     * 核心线程数
     */
    private int coreSize;
    /**
     * 最大线程数
     */
    private int maxCoreSize = 200;
    /**
     * 队列长度
     */
    private int queueCapacity = Integer.MAX_VALUE;
    /**
     * 线程池任务等待时间
     */
    private int awaitTerminationSeconds = 60;
    /**
     * 线程池名称
     */
    private String threadName = "spring-Thread-";
    /**
     * 拒绝策略名称
     */
    private String rejectedName = "";
    /**
     * 拒绝策略:
     * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
     * ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
     * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务
     * ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
     */
    private RejectedExecutionHandler rejectedExecutionHandler;

    public RejectedExecutionHandler getRejectedExecutionHandler() {
        switch (getThreadName()) {
            case "callerRunsPolicy":
                return new ThreadPoolExecutor.CallerRunsPolicy();
            case "discardPolicy":
                return new ThreadPoolExecutor.DiscardPolicy();
            case "discardOldestPolicy":
                return new ThreadPoolExecutor.DiscardOldestPolicy();
            default:
                return new ThreadPoolExecutor.AbortPolicy();
        }
    }
}

bean定义

package com.org.drango.config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;



@EnableAsync
@Configuration
public class ThreadExecutorConfig {

    //第一个ThreadPool
    @Primary
    @Bean(name = "properties1")
    @ConfigurationProperties(prefix = "spring.pool.executor1")
    public ThreadPoolExecutorProperties executorProperties1() {
        return new ThreadPoolExecutorProperties();
    }

    @Bean(name = "threadPool1")
    public ThreadPoolTaskExecutor threadPool1(@Qualifier("properties1") ThreadPoolExecutorProperties properties1) {
        ThreadPoolTaskExecutor  executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(properties1.getCoreSize());
        executor.setMaxPoolSize(properties1.getMaxCoreSize());
        executor.setAwaitTerminationSeconds(properties1.getAwaitTerminationSeconds());
        executor.setQueueCapacity(properties1.getQueueCapacity());
        executor.setThreadNamePrefix(properties1.getThreadName());
        executor.setRejectedExecutionHandler(properties1.getRejectedExecutionHandler());
        // Spring 一定要initialize 
        executor.initialize();
        return executor;
    }

    @Primary
    @Bean(name = "properties2")
    @ConfigurationProperties(prefix = "spring.pool.executor2")
    public ThreadPoolExecutorProperties executorProperties2() {
        return new ThreadPoolExecutorProperties();
    }

    //第二个ThreadPool
    @Bean("threadPool2")
    public ThreadPoolTaskExecutor threadPool2(@Qualifier("properties2") ThreadPoolExecutorProperties properties2) {
        ThreadPoolTaskExecutor  executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(properties2.getCoreSize());
        executor.setMaxPoolSize(properties2.getMaxCoreSize());
        executor.setAwaitTerminationSeconds(properties2.getAwaitTerminationSeconds());
        executor.setQueueCapacity(properties2.getQueueCapacity());
        executor.setThreadNamePrefix(properties2.getThreadName());
        executor.initialize();
        return executor;
    }

}

配置文件

#ThreadPool
spring.pool.executor1.core-size=3
spring.pool.executor1.max-core-size=5
spring.pool.executor1.queue-Capacity=100
spring.pool.executor1.thread-name=async1
spring.pool.executor1.rejected-name=async1

spring.pool.executor2.core-size=15
spring.pool.executor2.max-core-size=20
spring.pool.executor2.queue-Capacity=50
spring.pool.executor2.thread-name=async2

测试用例

@SneakyThrows
    @Override
    @Async("threadPool2")
    public void async1(CountDownLatch count) {
        TimeUnit.SECONDS.sleep(2);
        LongAdder adder = new LongAdder();
        ThreadPoolExecutor threadPoolExecutor = threadPool2.getThreadPoolExecutor();
        System.out.println("异步执行了====="+ Thread.currentThread().getName());
        System.out.println(threadPoolExecutor);
        count.countDown();
    }

console log