热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringBoot使用@Async异步多线程执行

SpringBoot使用Async异步多线程执行1、无返回值2、有返回值第一次使用,也采了好多坑,这里记录下。在方法上加上Async注解,

SpringBoot使用@Async异步多线程执行

  • 1、无返回值
  • 2、有返回值

第一次使用,也采了好多坑,这里记录下。

在方法上加上@Async注解,不起作用时检查下面几点:

  • 调用者和@Async注解使用的方法在一个类中时候不起作用,原因是这个注解需要经过代理对象进行调用才有效(我的解决办法:分开放在不同的类中)。

  • 在启动类上开启注解,也就是在启动类xxxApplication.java 上加上注解@EnableAsync

  • 在这里插入图片描述

  • 使用&#64;Async注解的方法归结为两种&#xff1a;没有返回值&#xff0c;有返回值&#xff08;返回值类型必须是Future类型&#xff0c;return new AsyncResult<>(xxxx);&#xff09;


1、无返回值

比较简单&#xff0c;在方法上加上和&#64;Async注解即可&#xff0c;有线程池方法的在后面括号中写上线程池方法名&#xff08;&#64;Async&#xff08;“myAsync”&#xff09;&#xff09;&#xff0c;不要忘了在启动类上加上注解&#64;EnableAsync。

下面是一个练习小Demo

/**
* 任务类&#xff1a;没有配置线程池
*/

&#64;Component
&#64;Slf4j
public class TaskDemo {&#64;Asyncpublic void test1() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时1500Thread.sleep(1500);} catch (InterruptedException e) {e.printStackTrace();} }&#64;Asyncpublic void test2() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时200Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}&#64;Asyncpublic void test3() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时400Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}}&#64;Asyncpublic void test4() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时900Thread.sleep(900);} catch (InterruptedException e) {e.printStackTrace();}}&#64;Asyncpublic void test5() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时1000Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}
}

其他类中调用

private TaskDemo taskDemo;&#64;GetMapping("/get")public void get() {log.info("开始");long begin &#61; System.currentTimeMillis();try {taskDemo.test1();taskDemo.test2();taskDemo.test3();taskDemo.test4();taskDemo.test5(); } catch (InterruptedException | ExecutionException e) {e.printStackTrace();}log.info("任务完成&#xff1a;耗时{}", System.currentTimeMillis() - begin);}&#64;Autowiredpublic void setTaskDemo(TaskDemo taskDemo) {this.taskDemo &#61; taskDemo;}

结果&#xff1a;任务完成&#xff1a;耗时1519

2、有返回值

注意&#xff1a;如果有返回值时候&#xff0c;返回值一定是Future

/**
* 任务类&#xff1a;没有配置线程池
*/

&#64;Component
&#64;Slf4j
public class TaskDemo {&#64;Asyncpublic Future<Integer> test1() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时1500Thread.sleep(1500);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResult<>(1500);}&#64;Asyncpublic Future<Integer> test2() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时200Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResult<>(200);}&#64;Asyncpublic Future<Integer> test3() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时400Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResult<>(400);}&#64;Asyncpublic Future<Integer> test4() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时900Thread.sleep(900);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResult<>(900);}&#64;Asyncpublic Future<Integer> test5() {String name &#61; Thread.currentThread().getName();log.info("线程名称&#xff1a;" &#43; name);try {// 模拟一系列数据操作&#xff0c;耗时1000Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return new AsyncResult<>(1000);}
}

调用类

private TaskDemo taskDemo;&#64;GetMapping("/get")public void get() {log.info("开始");long begin &#61; System.currentTimeMillis();try {Future<Integer> test1 &#61; taskDemo.test1();Future<Integer> test2 &#61; taskDemo.test2();Future<Integer> test3 &#61; taskDemo.test3();Future<Integer> test4 &#61; taskDemo.test4();Future<Integer> test5 &#61; taskDemo.test5();Integer integer1 &#61; 0;Integer integer2 &#61; 0;Integer integer3 &#61; 0;Integer integer4 &#61; 0;Integer integer5 &#61; 0;// 等待其他线程执行完毕,任务没有执行结束就一直等待&#xff0c;可以设置get的超时时间// test1.get(60, TimeUnit.SECONDS); // 设置超时时间&#xff0c;时间单位是秒// .isDone() 是判断线程执行完毕的标志&#xff0c;执行完毕返回truewhile (true){boolean done1 &#61; test1.isDone();boolean done2 &#61; test1.isDone();boolean done3 &#61; test1.isDone();boolean done4 &#61; test1.isDone();boolean done5 &#61; test1.isDone();boolean b &#61; done1 & done2 & done3 & done4 & done5;if (b){// .get()方法获取线程执行结果&#xff0c;具有阻塞状态&#xff0c;所以需要死循环进行判断integer1 &#61; test1.get();integer2 &#61; test2.get();integer3 &#61; test3.get();integer4 &#61; test4.get();integer5 &#61; test5.get();break;}}int i &#61; integer1 &#43; integer2 &#43; integer3 &#43; integer4 &#43; integer5;log.info(i &#43; "$");// 执行结果} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}log.info("统计完成&#xff1a;耗时{}", System.currentTimeMillis() - begin);}&#64;Autowiredpublic void setTaskDemo(TaskDemo taskDemo) {this.taskDemo &#61; taskDemo;}

结果&#xff1a;
在这里插入图片描述

没有使用多线程之前执行的结果&#xff1a;
在这里插入图片描述

可以看到&#xff0c;执行时间减少了很多&#xff01;欢迎留言讨论哦&#xff01;


推荐阅读
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • 本文探讨了如何通过一系列技术手段提升Spring Boot项目的并发处理能力,解决生产环境中因慢请求导致的系统性能下降问题。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • Java多线程实现:从1到100分段求和并汇总结果
    本文介绍如何使用Java编写一个程序,通过10个线程分别计算不同区间的和,并最终汇总所有线程的结果。每个线程负责计算一段连续的整数之和,最后将所有线程的结果相加。 ... [详细]
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • springMVC JRS303验证 ... [详细]
  • 本文详细探讨了在微服务架构中,使用Feign进行远程调用时出现的请求头丢失问题,并提供了具体的解决方案。重点讨论了单线程和异步调用两种场景下的处理方法。 ... [详细]
  • 使用lambda表达式排序Collections.sort(temp,(Stringa,Stringb)-{returnb.compareTo(a);});Collections ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
author-avatar
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有