热门标签 | 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中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • JUC并发编程——线程的基本方法使用
    目录一、线程名称设置和获取二、线程的sleep()三、线程的interrupt四、join()五、yield()六、wait(),notify(),notifyAll( ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • Spring Boot + RabbitMQ 消息确认机制详解
    本文详细介绍如何在 Spring Boot 项目中使用 RabbitMQ 的消息确认机制,包括消息发送确认和消息接收确认,帮助开发者解决在实际操作中可能遇到的问题。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 本文将从基础概念入手,详细探讨SpringMVC框架中DispatcherServlet如何通过HandlerMapping进行请求分发,以及其背后的源码实现细节。 ... [详细]
  • flea,frame,db,使用,之 ... [详细]
  • Spring Boot使用AJAX从数据库读取数据异步刷新前端表格
      近期项目需要是实现一个通过筛选选取所需数据刷新表格的功能,因为表格只占页面的一小部分,不希望整个也页面都随之刷新,所以首先想到了使用AJAX来实现。  以下介绍解决方法(请忽视 ... [详细]
  • spring(22)JdbcTemplate
    2019独角兽企业重金招聘Python工程师标准###1.导入jar包,必须jar包:c3p0、mysql-connector、beans、con ... [详细]
  • 关于进程的复习:#管道#数据的共享Managerdictlist#进程池#cpu个数1#retmap(func,iterable)#异步自带close和join#所有 ... [详细]
  • 大华股份2013届校园招聘软件算法类试题D卷
    一、填空题(共17题,每题3分,总共51分)1.设有inta5,*b,**c,执行语句c&b,b&a后,**c的值为________答:5 ... [详细]
  • 在iOS开发中,多线程技术的应用非常广泛,能够高效地执行多个调度任务。本文将重点介绍GCD(Grand Central Dispatch)在多线程开发中的应用,包括其函数和队列的实现细节。 ... [详细]
  • 深入理解Java多线程与并发机制
    本文探讨了Java多线程和并发机制的核心概念,包括多线程类的分类、执行器框架、并发容器及控制工具。通过详细解析这些组件,帮助开发者更好地理解和应用多线程技术。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
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社区 版权所有