Spring/SpringBoot自定义线程池

Spring/SpringBoot自定义线程池

在 Spring/SpringBoot 中,可以使用 @Configuration 和 @Bean 去设置线程池,用 @Value 去做线程池的参数配置。

依赖包:

引用 google 的 guava包。

复制代码
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

线程池配置:

复制代码
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.*;



@Configuration
public class ThreadPoolExecutorConfig {

    /**
     * 核心线程数, :冒号后面是默认值
     */
    @Value("${executor.core.pool.size:20}")
    private int corePoolSize;

    /**
     * 最大线程数, :冒号后面是默认值
     */
    @Value("${executor.max.pool.size:100}")
    private int maxPoolSize;

    /**
     * 没有任务执行时,线程的存活时间
     */
    @Value("${executor.keep.alive.time:2}")
    private int keepAliveTime;

    /**
     * 阻塞队列长度
     */
    @Value("${executor.blocking.queue.size:200}")
    private int blockingQueueSize;


    /**
     * 使用 @Bean 指定线程池的名称
     *
     */
    @Bean("myExecutor")
    public Executor myExecutor() {

        //阻塞队列长度
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(blockingQueueSize);

        //创建线程或线程池时指定有意义的线程名称,方便出错时回溯。名称如果过长,会被截断。
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("my-executor-%d").build();
        //可以自定义拒绝策略,也可以不加这个参数,构造方法会直接用默认的拒绝策略
        ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();

        return new ThreadPoolExecutor(corePoolSize, maxPoolSize,
                keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory, abortPolicy);


    }


    /**
     * 不同的业务,有时可以使用不同的线程池、不同的配置。
     * 如果核心业务跟普通业务,用同一个线程池,普通业务可能会占用过多的线程数,导致核心业务受影响。
     */
    @Bean("myExecutor2")
    public Executor myExecutor2() {

        //阻塞队列长度
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(blockingQueueSize);

        //创建线程或线程池时指定有意义的线程名称,方便出错时回溯。
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("my-executor2-%d").build();
        //可以自定义拒绝策略,也可以不加这个参数,构造方法会直接用默认的拒绝策略
        ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();

        return new ThreadPoolExecutor(corePoolSize, maxPoolSize,
                keepAliveTime, TimeUnit.SECONDS, workQueue, threadFactory, abortPolicy);
    }

}

配置参数:

可以写到配置中心里面,如果没有配置中心,放到 propeties 文件也行。

复制代码
executor.core.pool.size=20
executor.max.pool.size=100
executor.keep.alive.time=2
executor.blocking.queue.size=200

使用线程池:

日志框架自行补充,可以在Service类上面用 lombok的 @Slf4j 注解,也可以用其他的日志。

复制代码
@Service
@Slf4j
public class MyService {

    @Resource(name = "myExecutor")
    private Executor executor;

    public void execute() {
        executor.execute(() -> log.info("线程池执行任务."));

    }

}

运行,查看日志:

复制代码
INFO 18876 --- [ my-executor-0] com.example.demo.threadpool.MyService    : 线程池执行任务.

可以看到 线程池已经执行任务。日志中的 线程名称 是 my-executor 开头的。

把MyService 类中的 (name = "myExecutor") 换成 (name = "myExecutor2") ,再次运行,查看日志:

复制代码
INFO 18876 --- [ my-executor2-0] com.example.demo.threadpool.MyService    : 线程池执行任务.

可以看到日志,线程池已经执行任务。 线程名称 变成 了 my-executor2 开头的了。

创建线程或线程池时,指定有意义的线程名称,方便出错时回溯。

Spring / 普通Java项目的自定义线程池

详情见:https://www.cnblogs.com/expiator/p/17140760.html

相关推荐
道友可好1 小时前
Superpowers:给 AI 编程助手装上超能力
前端·人工智能·后端
凯尔萨厮1 小时前
创建Hibernate Web项目(配置类)
后端·hibernate
hyunbar7771 小时前
NOT IN 的 NULL 陷阱:一次 UNION 数据"神秘消失"
后端
张小凡vip1 小时前
Spring Boot集成Kafka完整版
spring boot·kafka·linq
basketball6162 小时前
Go语言从入门到进阶:8. 接口
开发语言·后端·golang
明月_清风2 小时前
深入 Go 并发编程:从 Goroutine 到 Channel 的系统性避坑指南
后端·go
摇滚侠2 小时前
SpringBoot 升级,依赖冲突如何解决
java·spring boot·spring
雪隐2 小时前
AI股票小助手04-miniQMT数据采集
人工智能·后端
苏三说技术2 小时前
MybatisPlus Pro 来了,CURD开发效率直接拉满!
后端
小江的记录本2 小时前
【JVM虚拟机】类加载机制:类加载器、双亲委派模型、好处、破坏双亲委派的场景(附《思维导图》+《面试高频考点清单》)
java·jvm·spring boot·后端·python·spring·面试