Spring Boot 2.x实战20 - 深入Spring Boot 5 - 多线程任务

5 多线程任务和计划任务

5.1 Task Executor

Spring给我们提供了异步多线程任务的功能,我们只需通过@EnableAsync开启异步多线程任务的支持,然后使用@Async来注解需要执行的异步多线程任务。

@EnableAsync通过导入AsyncConfigurationSelector选择配置,在配置(ProxyAsyncConfiguration)中注册了AsyncAnnotationBeanPostProcessor

这个BeanPostProcessor@Async(或 EJB 3.1的@Asynchronous)注解生效的同时,需要一个类型为TaskExecutor的Bean既可以运行。

在我们使用Spring开发时,我们除了使用@EnableAsync@Async注解之外,我们还需定义类型为TaskExecutor的 Bean。庆幸的的是,Spring Boot为我们提供了自动配置TaskExecutionAutoConfiguration,它自动为我们注册了一个Bean名称为applicationTaskExecutorThreadPoolTaskExecutorTaskExecutor的实现类)。

在Spring Boot中,我们只需使用@EnableAsync@Async。下面我们做个简单的异步多线程任务的演示。

首先,我们在入口类开启对异步多线程任务的支持:

@SpringBootApplication
@EnableAsync // SpringBootInDepthApplication是一个配置类,也可以注解在其他的配置类上
public class SpringBootInDepthApplication {}

我们定义一个包含异步多线程任务的类:

@Component
@Slf4j
public class AsyncTask {
    @Async //还可以注解在类上,意味着整个类的所有方法都是异步的。
    public void loopPrint(Integer i){
        log.info("当前计数为:" + i);
    }
}

通过CommandLineRunner检验:

@Bean
CommandLineRunner asyncTaskClr(AsyncTask asyncTask){
   return args -> {
      for(int i = 0; i < 10 ;i++){
         asyncTask.loopPrint(i);
      }
   };
}

Spring Boot 2.x实战20 - 深入Spring Boot 5 - 多线程任务_第1张图片
结果我们可以看出,异步任务不是使用的主线程restartedMain,而是使用一个线程池,默认有8个线程,线程名以task-开头,循环的执行结果是乱序的,这也意味着任务是并发执行的。

我们还可以通过spring.task.execution来对ThreadPoolTaskExecutor进行定制。

spring:
  task:
    execution:
      pool:
        core-size: 10 # 线程池核心线程数设置为10,默认是8
        max-size: 16 # 线程池最大线程数为16
      thread-name-prefix: mytask- #定制线程名前缀

我们再次执行检验:
Spring Boot 2.x实战20 - 深入Spring Boot 5 - 多线程任务_第2张图片
线程前缀已修改为mytask-,线程数也变成了10个。

当系统中有多个不同的异步多线程任务的时候,我们可以给特定的任务指定ThreadPoolTaskExecutor。Spring

Boot为我们提供了TaskExecutorBuilder的Bean,可以用它新建我们定制的ThreadPoolTaskExecutor

@Bean
ThreadPoolTaskExecutor customTaskExecutor(TaskExecutorBuilder taskExecutorBuilder){
   return taskExecutorBuilder
         .threadNamePrefix("customTask-")
         .corePoolSize(5)
         .build();
}

@Bean
ThreadPoolTaskExecutor myTaskExecutor(TaskExecutorBuilder taskExecutorBuilder){
   return taskExecutorBuilder
         .threadNamePrefix("myTask-")
         .corePoolSize(6)
         .build();
}

新建2个ThreadPoolTaskExecutor的Bean的名称分别为customTaskExecutormyTaskExecutor,此时Spring Boot将不会自动注册ThreadPoolTaskExecutor的Bean了(因为Bean上注解了@ConditionalOnMissingBean(Executor.class))。我们在AsyncTask新增一个异步方法,两个方法分别使用两个ThreadPoolTaskExecutor

@Component
@Slf4j
public class AsyncTask {
    @Async("myTaskExecutor")
    public void loopPrint(Integer i){
        log.info("当前计数为:" + i);
    }

    @Async("customTaskExecutor")
    public void loopPrint2(Integer i){
        log.info("当前计数为:" + i);
    }
}

修改CommandLineRunner进行校验:

@Bean
CommandLineRunner asyncTaskClr(AsyncTask asyncTask){
   return args -> {
      for(int i = 0; i < 10 ;i++){
         asyncTask.loopPrint(i);
      }

      for(int i = 0; i < 10 ;i++){
         asyncTask.loopPrint2(i);
      }
   };
}

Spring Boot 2.x实战20 - 深入Spring Boot 5 - 多线程任务_第3张图片

新书推荐:

我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html

Spring Boot 2.x实战20 - 深入Spring Boot 5 - 多线程任务_第4张图片

主要包含目录有:

第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和屁股里(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。

你可能感兴趣的:(Spring,Boot2.x实战全集,Spring,Boot2.x实战,-,Spring,Boot)