SpringBoot中自定义线程池(@Async使用自定义线程池)

简介: SpringBoot中自定义线程池(@Async使用自定义线程池)

前言

以前负责的一个项目,从单体架构往微服务架构迁移时,引入了Consul作为服务配置中心,然后导致所有的异步定时任务(@schedule+@Async)都不执行了;跟源码发现Consul作为服务配置中心时会在client端起一个定时任务线程池(核心线程数和最大线程数均为1)其伦村Consul Server中的服务配置;

由于@Async默认使用SpringBoot自带的线程池,而这个线程池已经被Consul创建,并且核心线程数和最大线程数都为1,就导致@Async一直拿不到可用的线程,进而所有的定时任务都没有执行;

当时的解决方案:

  • 自定义线程池,@Async使用时指定线程池名称,执行异步任务。

自定义线程池

在@Configuration类中通过@Bean的方式注入一个ThreadPoolTaskExecutor到Spring容器;

@Bean("myExecutor")
public ThreadPoolTaskExecutor mqInvokeAysncExecutor() {

    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    // 线程池中的线程名前缀
    executor.setThreadNamePrefix("log-message-");
    // 设置线程池关闭的时候需要等待所有任务都完成 才能销毁其他的Bean
    executor.setWaitForTasksToCompleteOnShutdown(true);
    // 设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
    executor.setAwaitTerminationSeconds(120);
    executor.setCorePoolSize(4);
    executor.setMaxPoolSize(16);
    // 任务阻塞队列的大小
    executor.setQueueCapacity(20000);
    return executor;
}

使用自定义线程池

1)@Async中使用

在使用的方法上面添加@Async(“自定义线程池类beanName”)注解;

public class AsyncTest {

    // 指定使用哪个线程池,不指定则使用spring默认的线程池
    @Async("myExecutor")
    public void executeAsync() {
        System.out.println("executeAsync");
    }
}

2)CompletableFuture中使用

当使用CompletableFuture.runAsync()方法异步执行一系列任务时,可以在方法的第二个参数中指定用哪个线程池执行任务;

public class ImportOrderLogMsgProducer {

    @Resource(name = "myExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;



    public void testAsync(LogMessage logMessage) {

        CompletableFuture.runAsync(() -> {

            try {
                // do something
            } catch (Exception e) {
                log.error("... catch:{}", e.getMessage(), e);
            }

        }, threadPoolTaskExecutor);
    }
}
相关文章
|
3月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
229 2
|
11月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
524 60
【Java并发】【线程池】带你从0-1入门线程池
|
12月前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
9月前
|
Java
线程池是什么?线程池在实际工作中的应用
总的来说,线程池是一种有效的多线程处理方式,它可以提高系统的性能和稳定性。在实际工作中,我们需要根据任务的特性和系统的硬件能力来合理设置线程池的大小,以达到最佳的效果。
269 18
|
10月前
|
Java 测试技术 Spring
SpringBoot+@Async注解一起用,速度提升
本文介绍了异步调用在高并发Web应用性能优化中的重要性,对比了同步与异步调用的区别。同步调用按顺序执行,每一步需等待上一步完成;而异步调用无需等待,可提升效率。通过Spring Boot示例,使用@Async注解实现异步任务,并借助Future对象处理异步回调,有效减少程序运行时间。
323 3
|
11月前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
Java 应用服务中间件 Maven
传统maven项目和现在spring boot项目的区别
Spring Boot:传统 Web 项目与采用 Spring Boot 项目区别
737 0
传统maven项目和现在spring boot项目的区别
|
XML Java 数据库连接
创建springboot项目的基本流程——以宠物类别为例
创建springboot项目的基本流程——以宠物类别为例
249 0
创建springboot项目的基本流程——以宠物类别为例
|
存储 机器学习/深度学习 IDE
SpringBoot 项目与被开发快速迁移|学习笔记
快速学习 SpringBoot 项目与被开发快速迁移
SpringBoot 项目与被开发快速迁移|学习笔记
|
Java Spring
自定义SpringBoot项目的启动Banner
``Banner``是``SpringBoot``框架一个特色的部分,其设计的目的无非就是一个框架的标识,其中包含了版本号、框架名称等内容,既然``SpringBoot``为我们提供了这个模块,它肯定也是可以更换的这也是``Spring``开源框架的设计理念。

热门文章

最新文章