前言

在日常开发过程中,会遇到一些需求是和主业务逻辑低耦合的,不要求和主业务逻辑同步进行,比如记录日志信息、发送消息通知电子邮件、生成PDF合同和导出报表等需求,而且,这些需求往往处理起来比较耗时。这个时候就需要开启新线程处理这些耗时多的业务,为主业务逻辑以最快速度执行完毕保驾护航。

在Spring Boot项目中通过注解开启异步线程,仅仅需要做两件事情:① 在启动类添加注解@EnableAsync,开启异步调用,②在方法上添加注解@Async("yourThreadPool"),其中,yourThreadPool为自定义线程池,可以使用系统默认线程池。

自定义线程池

在Spring Boot项目中自定义线程池:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor; /**
* 自定义线程池
*
* @author Wiener
* @date 2020/7/17 16:44
*/
@EnableAsync
@Configuration
public class TaskPoolConfig {
@Bean("east7TaskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("east7Task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
}

由于这个配置类中添加了@EnableAsync注解,故在项目启动类中就不必再次添加了。下面枚举ThreadPoolTaskExecutor中各个属性的含义:

  1. corePoolSize:线程池创建时候初始化的线程数;
  2. maxPoolSize:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程;
  3. queueCapacity:用来设置缓冲队列的容量,Set the capacity for the ThreadPoolExecutor's BlockingQueue.
  4. keepAliveSeconds:允许线程的空闲时间60秒,当超过了核心线程数外的线程在空闲时间到达之后会被销毁;
  5. threadNamePrefix:线程池名的前缀,用于快速定位当前任务所在的线程池;
  6. rejectedExecutionHandler:线程池对拒绝任务的处理策略,这里采用了CallerRunsPolicy;
  7. waitForTasksToCompleteOnShutdown:默认值为false,这里赋值true,用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean,这样这些异步任务的销毁就会先于其它对象(如数据库连接池对象)销毁;
  8. awaitTerminationSeconds:设置线程池中任务的等待时间,如果超过这个时间还没有销毁就强制销毁,以确保应用最后能够被关闭,而不被阻塞。

实践

在未自定义线程池的时候,Spring Boot默认使用SimpleAsyncTaskExecutor这个线程池,但此线程池不是真正意义上的线程池,因为线程不重用,每次调用都会创建一个新的线程。下面通过自定义线程池演示如何使用异步注解调用hello函数。示例代码:

    @GetMapping("/testSync")
public String testSync() {
userService.hello();
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
logger.info("testSync 方法继续执行,当前时间:{}", date);
return "执行结束";
}

在userService及其实现类添加函数hello(),并且使用自定义线程池执行异步任务:

    @Async ("east7TaskExecutor")
@Override
public void hello() {
try {
logger.info("同学们,课间休息时间到了");
Thread.sleep(3000);
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); logger.info("休息结束,继续上课,当前时间:{}", date);
} catch (InterruptedException e) {
logger.error("执行失败", e);
}
}

启动项目,请求testSync(),在控制台可以看到如下执行结果,说明添加异步执行功能成功。

testSync 方法继续执行,当前时间:2020-07-17 16:22:19
同学们,课间休息时间到了
休息结束,继续上课,当前时间:2020-07-17 16:22:22

在控制台中可以找到包含关键字east7Task的如下类似日志,说明执行任务时使用了自定义的线程池。

INFO 9904 --- [east7Task-2]

Reference

https://mp.weixin.qq.com/s?__biz=MzIxNDEyMzE3OQ%3D%3D&mid=2247487853&idx=1&sn=f399a94d70ebe603aa62f789fac945fc&scene=45#wechat_redirect

Spring注解之@Async:Spring Boot实现异步调用的更多相关文章

  1. Spring @Async之一:实现异步调用示例

    什么是“异步调用”? “异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行:异步调用指程序在顺序执行时,不等待异步调用的语句返回结果 ...

  2. spring boot实现异步调用

    今天在这里学习下使用springboot的异步调用async 首先使用@EnableAsync开启异步功能 /** * @author fengzp * @date 17/5/8 * @email f ...

  3. Spring注解 系列之Spring常用注解总结

    参考:Spring系列之Spring常用注解总结 (1) Resource 默认是byName的方式进行bean配置,@AutoWired默认是按照byType的方式进行装配bean的:(2)Comp ...

  4. Spring注解开发之Spring常用注解

    https://blog.csdn.net/Adrian_Dai/article/details/80287557主要的注解使用: 本文用的Spring源码是4.3.16@Configuration ...

  5. Spring注解配置、Spring aop、整合Junit——Spring学习 day2

    注解配置: 1.为主配置文件引入新的命名空间(约束) preference中引入文件 2.开启使用注解代理配置文件 <?xml version="1.0" encoding= ...

  6. Spring Boot使用@Async实现异步调用

    原文:http://blog.csdn.net/a286352250/article/details/53157822 项目GitHub地址 : https://github.com/FrameRes ...

  7. Spring中@Async注解实现“方法”的异步调用

    原文:http://www.cnblogs.com/zhengbin/p/6104502.html 简单介绍: Spring为任务调度与异步方法执行提供了注解支持.通过在方法上设置@Async注解,可 ...

  8. Spring源码学习之:@async 方法上添加该注解实现异步调用的原理

    在我们使用spring框架的过程中,在很多时候我们会使用@async注解来异步执行某一些方法,提高系统的执行效率.今天我们来探讨下 spring 是如何完成这个功能的.    spring 在扫描be ...

  9. Spring Boot 异步请求和异步调用,一文搞定

    一.Spring Boot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如 ...

  10. 如何在Spring异步调用中传递上下文

    以下文章来源于aoho求索 ,作者aoho 1. 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步 ...

随机推荐

  1. typora编辑数学公式

    最后,需要补充两点: 1.如果要导出为docx,需要安装pandoc https://github.com/jgm/pandoc/releases/tag/3.6.3 2.如果要自己写代码,比如输入\ ...

  2. Vulnhub-Hackme

    一.靶机搭建 选择扫描虚拟机 选择路径即可 二.信息收集 靶机信息 Name: hackme: 1 Date release: 18 Jul 2019 难度:初级,目标是通过web漏洞获得有限的权限访 ...

  3. ppt 字少怎么办

    1.加图标 2.加色块 3.加图片 最终效果

  4. allure 报告空白

    在pycharm 运行py文件后生成的报告内容空白: 尝试方法 替换allure版本号---不好用 用命令生成.html测试报告,再以浏览器形式打开 ** ** 命令 allure generate ...

  5. linux php安装mongodb 扩展

    下载扩展 首先从这个网站选择适合你当前 php 版本的的 mongodb 扩展 https://pecl.php.net/package/mongodb wget https://pecl.php.n ...

  6. 一文速通Python并行计算:02 Python多线程编程-threading模块、线程的创建和查询与守护线程

    一文速通 Python 并行计算:02 Python 多线程编程-threading 模块.线程的创建和查询与守护线程 摘要: 本文介绍了 Python threading 模块的核心功能,包括线程创 ...

  7. study Python3【4】字符串的判断

    判断类型: result为True和False str = '1122abc' str.isalnum()是数字或者字母 str = 'MDCA' str.isalpha() 是字母 str = '1 ...

  8. datasnap的回调广播

    感觉中的datasnap千孔百疮,到xe10已经具备冲击成千上万用户并发的能力了.应该放心用于项目实战了.补课研究10.1 datasnap开发手册. 用到的方法: (1)TDBXCallback机制 ...

  9. 房价预测数据清洗全流程:从数据采集到可视化分析(Python实战)

    在房价预测项目中,数据清洗是至关重要的环节.它不仅决定了模型的准确性,还直接影响后续分析的可靠性.本文将以波士顿房价数据集为例,通过Python的Pandas.Matplotlib等工具,详细讲解数据 ...

  10. Docker安装及使用,Docker 安装MySQL、安装Tomcat、安装RabbitMQ

    CentOS7安装Docker Docker从1.13版本之后采用时间线的方式作为版本号,分为社区版CE和企业版EE. 社区版是免费提供给个人开发者和小型团体使用的,企业版会提供额外的收费服务,比如经 ...