热门标签 | 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中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 本文探讨了在Java多线程环境下,如何确保具有相同key值的线程能够互斥执行并按顺序输出结果。通过优化代码结构和使用线程安全的数据结构,我们解决了线程同步问题,并实现了预期的并发行为。 ... [详细]
  • 本文详细介绍了 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是如何被执行的。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Java多线程实现:从1到100分段求和并汇总结果
    本文介绍如何使用Java编写一个程序,通过10个线程分别计算不同区间的和,并最终汇总所有线程的结果。每个线程负责计算一段连续的整数之和,最后将所有线程的结果相加。 ... [详细]
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
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社区 版权所有