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

相关推荐
唐青枫4 分钟前
别只会写 fn:Zig 函数、错误处理、泛型与回调实战
后端
Rain的Java大神之路7 分钟前
Docker搭建Redis集群完全指南
java·运维·redis·后端·docker·容器·架构
jj_ccwgw18 分钟前
Kafka KRaft 多机集群安装指南
后端
小蒜学长29 分钟前
基于Django的社区团购购物平台的设计与实现(代码+数据库+LW)
数据库·后端·python·django
灯澜忆梦30 分钟前
【基于GO的Web开发9】gin框架返回json
前端·后端·golang·gin
kymjs张涛36 分钟前
DeepSeek Harness源码分析:非 AI 开发者的 Agent 学习总结
前端·后端·面试
jj_ccwgw38 分钟前
UOS系统 Kafka KRaft 集群安装指南
后端
rannn_11139 分钟前
Java 后端面试题总结:点赞功能怎么实现?
java·后端·面试
程序员贺加贝41 分钟前
业务操作日志不是字段审计:快照 Diff、幂等账本与业务语义建模
spring boot·架构
__zRainy__1 小时前
Node系列 · 数据库:MySQL 安装
数据库·后端·mysql·node.js