spring boot中使用@Async实现异步调用任务
作者:林祥纤 发布时间:2023-04-25 13:35:18
标签:spring,boot,异步调用
什么是“异步调用”?
“异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序。
同步调用
下面通过一个简单示例来直观的理解什么是同步调用:
定义Task类,创建三个处理函数分别模拟三个执行任务的操作,操作消耗时间随机取(10秒内)
package com.kfit.task;
import java.util.Random;
import org.springframework.stereotype.Component;
/**
* 定义3个任务
* @author Angel(QQ:412887952)
* @version v.0.1
*/
@Component
publicclass Task1 {
//定义一个随机对象.
publicstatic Random random =new Random();
//任务一;
publicvoid doTaskOne() throws Exception {
System.out.println("开始做任务一");
longstart = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
longend = System.currentTimeMillis();
System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
}
//任务二;
publicvoid doTaskTwo() throws Exception {
System.out.println("开始做任务二");
longstart = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
longend = System.currentTimeMillis();
System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
}
//任务3;
publicvoid doTaskThree() throws Exception {
System.out.println("开始做任务三");
longstart = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
longend = System.currentTimeMillis();
System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
}
}
编写一个访问方法:
//测试task1.
@RequestMapping("/task1")
public String task1() throws Exception{
task1.doTaskOne();
task1.doTaskTwo();
task1.doTaskThree();
return"task1";
}
运行可以看到类似如下输出:
开始做任务一
完成任务一,耗时:4156毫秒
开始做任务二
完成任务二,耗时:557毫秒
开始做任务三
完成任务三,耗时:6171毫秒
异步调用
上述的同步调用虽然顺利的执行完了三个任务,但是可以看到执行时间比较长,若这三个任务本身之间不存在依赖关系,可以并发执行的话,同步调用在执行效率方面就比较差,可以考虑通过异步调用的方式来并发执行。
在Spring Boot中,我们只需要通过使用@Async注解就能简单的将原来的同步函数变为异步函数,Task类改在为如下模式:
package com.kfit.task;
import java.util.Random;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* 定义3个任务
* @author Angel(QQ:412887952)
* @version v.0.1
*/
@Component
publicclass Task2 {
//定义一个随机对象.
publicstatic Random random =new Random();
//任务一;
@Async
publicvoid doTaskOne() throws Exception {
System.out.println("开始做任务一");
longstart = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
longend = System.currentTimeMillis();
System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
}
//任务二;
@Async
publicvoid doTaskTwo() throws Exception {
System.out.println("开始做任务二");
longstart = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
longend = System.currentTimeMillis();
System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
}
//任务3;
@Async
publicvoid doTaskThree() throws Exception {
System.out.println("开始做任务三");
longstart = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
longend = System.currentTimeMillis();
System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
}
}
为了让@Async注解能够生效,还需要在Spring Boot的主程序中配置@EnableAsync,如下所示:
@SpringBootApplication
@EnableAsync
publicclass App {
//省略其它代码…
}
编写测试方法:
//测试task2.
@RequestMapping("/task2")
public String task2() throws Exception{
task2.doTaskOne();
task2.doTaskTwo();
task2.doTaskThree();
return"task2";
}
此时可以反复执行单元测试,您可能会遇到各种不同的结果,比如:
开始做任务一
开始做任务二
开始做任务三
完成任务三,耗时:57毫秒
完成任务二,耗时:3621毫秒
完成任务一,耗时:7419毫秒
来源:http://412887952-qq-com.iteye.com/blog/2309126


猜你喜欢
- 作为java中的一个重要理念,说起面向对象也是老生常谈了。在找资料的时候多是很专业的术语,又或者很多框架的知识点合集,其实大部分人刚看资料的
- 写了一个人民币小写转大写的方法,Java版本,思路很简单,没有测出什么Bug,有bug欢迎反馈public class RMBChange
- 这篇文章主要介绍了SpringBoot跨域Access-Control-Allow-Origin实现解析,文中通过示例代码介绍的非常详细,对
- 问题org.apache.ibatis.binding.BindingException: Invalid bound statement
- 由于对运算符重载不是多么理解诶,于是就百度了一下,结果发现一个解释很有趣的百度知道,分享看看。回答:+-*/这样的运算符重定义,比如你自定义
- 目录一、System.out.println(最简单)二、java.util.logging(相对简单)三、log4j(最强大)四、comm
- 权限提升方法:一种方法:1、在AndroidManifest.xml中的manifest节点中添加android:sharedUserId=
- 目录synchronized 实现原理适应性自旋(Adaptive Spinning)锁升级Java 对象头偏向锁(Biased Locki
- 演示代码: MenuExamples.java package swt_jface.demo5; import org.eclipse.sw
- 为什么说是常见问题整合呢,因为小编我就是Genymotion模板器最悲剧的使用者,该见过的问题,我基本都见过了,在此总结出这血的教训,望大家
- 根据约定,在使用java编程的时候应尽可能的使用现有的类库,当然你也可以自己编写一个排序的方法,或者框架,但是有几个人能写得比JDK里的还要
- ArrayList类List集合的实例化:List<String> l = new ArrayList<String>
- 本文是利用C# 实现FTP客户端的小例子,主要实现上传,下载,删除等功能,以供学习分享使用。思路:通过读取FTP站点的目录信息,列出对应的文
- 大家好,我是程序员田同学!今天上午收到一个需求,针对当前的系统开发一个对外开放的接口。既然是对外开放,那么调用者一定没有我们系统的Token
- 1、this关键字首先需要提醒的是,在整个Java之中,this是最麻烦的一个关键字,只要是代码开发,几乎都离不开this。在Java中th
- Process#waitFor()阻塞问题有时需要在程序中调用可执行程序或脚本命令:Process process = Runtime.ge
- 一、简介前面介绍了平时用到的大多数的多线程的例子,但在实际开发中使用的线程往往是大量的和更为复杂的,这时,每次都创建线程、启动线程。从性能上
- 泛型1、简单泛型泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。泛型暂时不指定类型,在使用时决定具体
- 释放公平锁(基于JDK1.7.0_40)1. unlock()unlock()在ReentrantLock.java中实现的,源码如下:pu
- 构造函数public class FileDemo { public static void