前言

上一篇中讲了关于TaskExecutor的一些相关知识,本篇就是实战篇,看看异步线程使如何使用的

正文

本篇文章使用springboot 2.2.1.RELEASE

一.前奏,直接使用,无任何配置

  1. 启动异步注解

在springboot启动类上添加注解@EnableAsync


  1. @SpringBootApplication
  2. @EnableAsync
  3. public class AsyncApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(AsyncApplication.class, args);
  6. }
  7. }
  1. 使用@Async注解

在需要的方法上使用@Async注解:


  1. public interface AsyncService {
  2. @Async
  3. void testAsync();
  4. @Async
  5. void testOne();
  6. }
  7. @Service
  8. public class AsyncServiceImpl implements AsyncService {
  9. private static final Logger log= LoggerFactory.getLogger(AsyncServiceImpl.class);
  10. @Override
  11. public void testAsync(){
  12. log.info("========testAsync运行=========="+Thread.currentThread().getName());
  13. }
  14. @Override
  15. public void testOne(){
  16. log.info("ThreadName:===one===="+Thread.currentThread().getName());
  17. }
  18. }
  1. controller 调用

    在controller层调用异步方法,注意,异步方法最好通过注入的方式调用,如果是同类方法或工具类方法,@Async可能不会取作用。

  1. @RestController
  2. @RequestMapping("/test")
  3. public class TestController {
  4. private final AsyncService asyncService;
  5. @Autowired
  6. public TestController(AsyncService asyncService) {
  7. this.asyncService = asyncService;
  8. }
  9. @GetMapping
  10. public String test(){
  11. asyncService.testAsync();
  12. asyncService.testOne();
  13. return "SUCCESS";
  14. }
  15. }
  1. 结果

  1. 2019-12-27 15:06:30.159 INFO 14756 --- [ task-1] c.e.async.service.impl.AsyncServiceImpl : ========testAsync运行==========task-1
  2. 2019-12-27 15:06:30.160 INFO 14756 --- [ task-2] c.e.async.service.impl.AsyncServiceImpl : ThreadName:===one====task-2
  1. 问题

很多人到这里就差不多完事了,我第一次用springboot的异步也是这样。其实这里还有问题:

  • 为什么线程名字是task-,而不是很多博客所说的SimpleAsyncTaskExecutor-
  • 为什么应用在启动时创建了一个名为:applicationTaskExecutorExecutor Service
  1. 原因

这是因为springboot版本的原因:

  • springboot2.1版本新加入了明为TaskExecutionAutoConfiguration的一个配置类,在没有实现Executor的情况是会自动注入一个nameapplicationTaskExecutorThreadPoolTaskExecutor,具体属性可以点进去看一看,这里就不细说了,关键源码如下:
  1. @Lazy
  2. @Bean(name = { APPLICATION_TASK_EXECUTOR_BEAN_NAME,
  3. AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME })
  4. @ConditionalOnMissingBean(Executor.class)
  5. public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
  6. return builder.build();
  7. }
  • springboot2.1版本之前,没有这个TaskExecutionAutoConfiguration类,所以才会是网上很多博客所说的SimpleAsyncTaskExecutor,具体的源码在下一篇文章中讲

二. ThreadPoolTaskExecutor

如何使用ThreadPoolTaskExecutor。


  1. @Configuration
  2. public class AsyncConfig {
  3. @Bean(name = "threadPoolTaskExecutor")
  4. public ThreadPoolTaskExecutor testTaskExecutor() {
  5. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  6. //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
  7. executor.setThreadNamePrefix("courses-schedule-");
  8. //最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
  9. executor.setMaxPoolSize(10);
  10. //核心线程数3:线程池创建时候初始化的线程数
  11. executor.setCorePoolSize(3);
  12. //缓冲队列0:用来缓冲执行任务的队列
  13. executor.setQueueCapacity(5);
  14. //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
  15. executor.setKeepAliveSeconds(60);
  16. // 当线程池已满,且等待队列也满了的时候,直接抛弃当前线程(不会抛出异常)
  17. // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
  18. // executor.initialize();
  19. return executor;
  20. }
  21. }

注意在使用@Async注解时在注解里面带上参数:@Async("threadPoolTaskExecutor")

三. ConcurrentTaskExecutor

如何使用ConcurrentTaskExecutor。


  1. @Bean(name = "concurrentTaskExecutor")
  2. public TaskExecutor concurrentTaskExecutor () {
  3. return new ConcurrentTaskExecutor(
  4. Executors.newFixedThreadPool(3));
  5. }

注意在使用@Async注解时在注解里面带上参数:@Async("concurrentTaskExecutor")

四 接口实现

AsyncConfig:这里需要实现AsyncConfigurer接口并重写里面得接口


  1. @Configuration
  2. public class AsyncConfig implements AsyncConfigurer {
  3. @Override
  4. public Executor getAsyncExecutor() {
  5. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  6. //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
  7. executor.setThreadNamePrefix("courses-schedule-");
  8. //最大线程数10:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
  9. executor.setMaxPoolSize(10);
  10. //核心线程数3:线程池创建时候初始化的线程数
  11. executor.setCorePoolSize(3);
  12. //缓冲队列0:用来缓冲执行任务的队列
  13. executor.setQueueCapacity(5);
  14. //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
  15. executor.setKeepAliveSeconds(60);
  16. // 当线程池已满,且等待队列也满了的时候,直接抛弃当前线程(不会抛出异常)
  17. // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
  18. // executor.initialize();
  19. return executor;
  20. }
  21. @Override
  22. public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
  23. return new AsyncExceptionHandler();
  24. }
  25. }

AsyncExceptionHandler:


  1. public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
  2. @Override
  3. public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
  4. System.out.println("Exception Cause - " + throwable.getMessage());
  5. System.out.println("Method name - " + method.getName());
  6. for (Object param : obj) {
  7. System.out.println("Parameter value - " + param);
  8. }
  9. }
  10. }

这个直接使用,不用做其他操作

五 说明

  1. 上面列出的方式,可以根据自己的需求做出选择,最好选择一种
  2. 如果存在两种及以上,请在使用@Async时加上需要使用哪一个处理,如果没有指明使用哪一种处理,最后会默认使用SimpleAsyncTaskExecutor来处理异步任务。

最后

本篇文章主要是使用方法,如何去使用springboot的异步线程。

项目源码

参考:

  1. Spring Boot Async Task Executor
  2. Spring 官方文档
  3. 新手也能看懂的 SpringBoot 异步编程指南
  4. TaskExecutionAutoConfiguration

springboot异步线程(二)的更多相关文章

  1. SpringBoot 异步线程简单三种样式

    引用:在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3.x ...

  2. springboot异步线程

    前言 最近项目中出现了一个问题,发现自己的定时器任务在线上没有执行,但是在线下测试时却能执行,最后谷歌到了这篇文章SpringBoot踩坑日记-定时任务不定时了?; 本篇文章主要以自己在项目中遇到的问 ...

  3. SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂)

    SpringBoot第十二集:度量指标监控与异步调用(2020最新最易懂) Spring Boot Actuator是spring boot项目一个监控模块,提供了很多原生的端点,包含了对应用系统的自 ...

  4. SpringBoot使用异步线程池实现生产环境批量数据推送

    前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在 ...

  5. springboot 中如何正确在异步线程中使用request

    起因: 有后端同事反馈在异步线程中获取了request中的参数,然后下一个请求是get请求的话,发现会偶尔出现参数丢失的问题. 示例代码: @GetMapping("/getParams&q ...

  6. Spring Boot系列二 Spring @Async异步线程池用法总结

    1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...

  7. SpringBoot异步使用@Async原理及线程池配置

    前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在Spring框架中应该如何去使用异步呢 使用步骤 完成异步操作一般有两种 ...

  8. C#中的线程二(Cotrol.BeginInvoke和Control.Invoke)

    C#中的线程二(Cotrol.BeginInvoke和Control.Invoke) 原文地址:http://www.cnblogs.com/whssunboy/archive/2007/06/07/ ...

  9. net异步线程获取返回值的三种方式

    方式一:endInvoke using System; using System.Collections.Generic; using System.Text; using System.Thread ...

随机推荐

  1. 拓展-教你手把手用纯CSS写轮播图

    先看成品图[示例网址:][1] [1]: https://huruji.github.io/css-imitate-js/slider/index.html一.随便说几句####css3动画效果的强大 ...

  2. 对 OAuth2 和非标 DingDing OAuth2 的一次尝试

    印象中工作以来还从来没搞过一次 OAuth2 的接入- -,似乎只停留在愉快的使用阶段.比如现在很多网站都接了 wx 二维码扫码登录或者微博登录.所以一直只是享受着这样的便利,却没有机会自己来搞一搞把 ...

  3. cgdsR 下载TCGA数据

    TCGA 的数据可以在5个组织机构获取,它们都提供了类似的接口来供用户下载数据. cgdsR 包是cBioPortal 提供的R包 http://www.cbioportal.org/rmatlab ...

  4. python 项目实战之随机杀死程序

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/10/14 13:54 # @Author : zoulixiang # @S ...

  5. [Gamma阶段]第八次Scrum Meeting

    Scrum Meeting博客目录 [Gamma阶段]第八次Scrum Meeting 基本信息 名称 时间 地点 时长 第八次Scrum Meeting 19/06/04 大运村寝室6楼 40min ...

  6. mysql 后台运行命令

    nohup mysql -u sa -pabcd1234 -e 'source /db.sql' &

  7. 深度解析 ASP.NET MVC 5

    ASP.NET MVC基础 IoC容器 ASP.NET MVC可扩展性 ASP.NET MVC Filters & Cache ASP.NET MVC AJAX ASP.NET MVC Cli ...

  8. 解决ffmpeg拉流转发频繁丢包问题max delay reached. need to consume packet

    软件: 1.流媒体服务器EasyDarwin-windows-8.1.0-1901141151 2.ffmpeg-20181001-dcbd89e-win64-static 3.直播源:rtsp:// ...

  9. -[UITableView copyWithZone:]: unrecognized selector sent to instance 0x7XXXXXX00

    -[UITableView copyWithZone:]: unrecognized selector sent to instance 0x7XXXXXX00 -[Class copyWithZon ...

  10. http状态码610,613

    610  请求超时 613  dns解析错误