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);
    }
}
相关文章
|
6天前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
|
6天前
|
Java 数据库连接 调度
面试题:用过线程池吗?如何自定义线程池?线程池的参数?
字节跳动面试题:用过线程池吗?如何自定义线程池?线程池的参数?
31 0
|
6天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
18 1
|
6天前
|
Java 程序员 数据库
Java线程池让使用线程变得更加高效
使用一个线程需要经过创建、运行、销毁三大步骤,如果业务系统每个线程都要经历这个过程,那会带来过多不必要的资源消耗。线程池就是为了解决这个问题而生,需要时就从池中拿取,使用完毕就放回去,池化思想通过复用对象大大提高了系统的性能。线程池、数据库连接池、对象池等都采用了池化技术,下面我们就来学习下线程池的核心知识、面试重点~
62 5
Java线程池让使用线程变得更加高效
|
6天前
|
监控 Java Spring
Spring Boot中一般如何使用线程池?
在Spring Boot应用程序中,合理地使用线程池可以有效地提高系统的性能和并发处理能力。本文将深入探讨Spring Boot中如何一般性地使用线程池,包括线程池的配置、使用方式以及一些最佳实践。
30 0
|
6天前
|
消息中间件 监控 前端开发
面试官:核心线程数为0时,线程池如何执行?
线程池是 Java 中用于提升程序执行效率的主要手段,也是并发编程中的核心实现技术,并且它也被广泛的应用在日常项目的开发之中。那问题来了,如果把线程池中的核心线程数设置为 0 时,线程池是如何执行的? 要回答这个问题,我们首先要了解在正常情况下,线程池的执行流程,也就是说当有一个任务来了之后,线程池是如何运行的? ## 1.线程池的执行流程 正常情况下(核心线程数不为 0 的情况下)线程池的执行流程如下: 1. **判断核心线程数**:先判断当前工作线程数是否大于核心线程数,如果结果为 false,则新建线程并执行任务。 2. **判断任务队列**:如果大于核心线程数,则判断任务队列是否
25 1
面试官:核心线程数为0时,线程池如何执行?
|
6天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
6天前
|
监控 Java 调度
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
|
6天前
|
设计模式 Java
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
|
6天前
|
缓存 Java 调度
为什么要使用线程池?线程创建不好使?
为什么要使用线程池?线程创建不好使?
20 0