SpringBoot集成篇(二) 异步调用Async
什么是异步调用?
异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。
如何实现异步调用?
多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式。
在非spring目项目中我们要实现异步调用的就是使用多线程方式,可以自己实现Runable接口或者集成Thread类,或者使用jdk1.5以上提供了的Executors线程池。
StrngBoot中则提供了很方便的方式执行异步调用。
按照官方示例开撸
代码入下
maven依赖:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.3.RELEASE</version>
- </parent>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
启动类:添加@EnableAsync注解
- @SpringBootApplication
- @EnableAsync
- public class Application{
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
Controller
只需在需要异步执行方法上添加@Async注解
- @RestController
- @RequestMapping("")
- public class AsyncTaskController {
- @RequestMapping("")
- public String doTask() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- this.task1();
- this.task2();
- this.task3();
- long currentTimeMillis1 = System.currentTimeMillis();
- return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
- }
- @Async
- public void task1() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(1000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task2() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(2000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task3() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(3000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- }
main函数运行spirngboot项目,启动完成后浏览器访问:
http://localhost:8080/
控制台:
- task1任务耗时:1012ms
- task2任务耗时:2009ms
- task3任务耗时:3004ms
等了一段浏览器时候输出入下:
- task任务总耗时:6002ms
异步并没有执行!
难道是代码写错了?反复检查了好几遍,并没有发现什么明显错误,想起spring对@Transactional注解时也有类似问题,spring扫描时具有@Transactional注解方法的类时,是生成一个代理类,由代理类去开启关闭事务,而在同一个类中,方法调用是在类体内执行的,spring无法截获这个方法调用。
豁然开朗,将异步任务单独放到一个类中,调整代码入下:
Controller
- @RequestMapping("")
- @RestController
- public class AsyncTaskController {
- @Autowired
- private AsyncTask asyncTask;
- @RequestMapping("")
- public String doTask() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- asyncTask.task1();
- asyncTask.task2();
- asyncTask.task3();
- long currentTimeMillis1 = System.currentTimeMillis();
- return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
- }
- }
异步任务类
- @Component
- public class AsyncTask {
- @Async
- public void task1() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(1000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task2() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(2000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task3() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(3000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- }
控制台:
- task1任务耗时:1012ms
- task2任务耗时:2009ms
- task3任务耗时:3004ms
访问浏览器结果入下:
- task任务总耗时:19ms
异步调用成功!
如何知道三个异步任务什么时候执行完,执行的结果怎样呢?可以采用添加Fature回调方式判断
代码入下:
异步任务类
- @Component
- public class AsyncTask {
- @Async
- public Future<String> task1() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(1000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- return new AsyncResult<String>("task1执行完毕");
- }
- @Async
- public Future<String> task2() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(2000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- return new AsyncResult<String>("task2执行完毕");
- }
- @Async
- public Future<String> task3() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(3000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- return new AsyncResult<String>("task3执行完毕");
- }
- }
Controller
- @RequestMapping("")
- @RestController
- public class AsyncTaskController {
- @Autowired
- private AsyncTask asyncTask;
- @RequestMapping("")
- public String doTask() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Future<String> task1 = asyncTask.task1();
- Future<String> task2 = asyncTask.task2();
- Future<String> task3 = asyncTask.task3();
- String result = null;
- for (;;) {
- if(task1.isDone() && task2.isDone() && task3.isDone()) {
- // 三个任务都调用完成,退出循环等待
- break;
- }
- Thread.sleep(1000);
- }
- long currentTimeMillis1 = System.currentTimeMillis();
- result = "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
- return result;
- }
- }
控制台输出:
- task1任务耗时:1000ms
- task2任务耗时:2001ms
- task3任务耗时:3001ms
浏览器输出:
- <span style="font-family:Simsun;font-size:14px;">task任务总耗时:4015ms</span>
异步调用成功,并且在所有任务都完成时程序才返回了结果!
SpringBoot集成篇(二) 异步调用Async的更多相关文章
- springboot:异步调用@Async
在后端开发中经常遇到一些耗时或者第三方系统调用的情况,我们知道Java程序一般的执行流程是顺序执行(不考虑多线程并发的情况),但是顺序执行的效率肯定是无法达到我们的预期的,这时就期望可以并行执行,常规 ...
- SpringBoot学习笔记(七):SpringBoot使用AOP统一处理请求日志、SpringBoot定时任务@Scheduled、SpringBoot异步调用Async、自定义参数
SpringBoot使用AOP统一处理请求日志 这里就提到了我们Spring当中的AOP,也就是面向切面编程,今天我们使用AOP去对我们的所有请求进行一个统一处理.首先在pom.xml中引入我们需要的 ...
- springboot:嵌套使用异步注解@Async还会异步执行吗
一.引言 在前边的文章<[springboot:使用异步注解@Async的那些坑>中介绍了使用@Async注解获取任务执行结果的错误用法,今天来分享下另外一种常见的错误. 二.代码演示 下 ...
- SpringBoot系列:Spring Boot异步调用@Async
在实际开发中,有时候为了及时处理请求和进行响应,我们可能会多任务同时执行,或者先处理主任务,也就是异步调用,异步调用的实现有很多,例如多线程.定时任务.消息队列等, 这一章节,我们就来讲讲@Async ...
- springboot 异步调用Async使用方法
引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3. ...
- springboot之异步调用@Async
原文:http://www.cnblogs.com/xuwenjin/p/8858050.html 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交 ...
- 170719、springboot编程之异步调用@Async
1.在pom.xml中增加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artif ...
- SpringBoot异步调用--@Async详解
1. 概述 在日常开发中,为了提高主线程的效率,往往需要采用异步调用处理,例如系统日志等.在实际业务场景中,可以使用消息中间件如RabbitMQ.RocketMQ.Kafka等来解决.假如对高可用 ...
- nodejs异步调用async
犹豫nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦,async的流程控制就是为了简化这些操作var async = require('async'); 1.serie ...
随机推荐
- OpenACC 绘制曼德勃罗集
▶ 书上第四章,用一系列步骤优化曼德勃罗集的计算过程. ● 代码 // constants.h ; ; ; ; const double xmin=-1.7; ; const double ymin= ...
- Linux命令详解----iostat
Linux系统出现了性能问题,一般我们可以通过top.iostat.free.vmstat等命令来查看初步定位问题.在一个以前看到系统监控工具,总在想那些监控工具的代理,如何收集系统性能信息,io性能 ...
- as3 XML类和XMLList类的区别
一.XML类和XMLList类的区别 AS3.0中,处理XML主要用到两个主类,XML类和XMLList类,这两个类的很多内容是共通的.应该有人会问,XML和XMLList的区别是什么? ...
- Maven可执行jar包
参考文章: Maven生成可以直接运行的jar包的多种方式(http://blog.csdn.net/xiao__gui/article/details/47341385) 一般,我们通过 > ...
- 快快快!27个提升效率的iOS开源库推荐(转)
CSDN移动将持续为您优选移动开发的精华内容,共同探讨移动开发的技术热点话题,涵盖移动应用.开发工具.移动游戏及引擎.智能硬件.物联网等方方面面.如果您想投稿.参与内容翻译工作,或寻求近匠报道,请发送 ...
- 批量压缩文件.net
C#调用 ICSharpCode.SharpZipLib.Zip 实现解压缩功能公用类 最近想用个解压缩功能 从网上找了找 加自己修改,个人感觉还是比较好用的,直接上代码如下 using System ...
- intelij创建MapReduce工程
1.创建一个maven工程 2.POM文件 <?xml version="1.0" encoding="UTF-8"?><project xm ...
- 扩展C#与元编程(二)
如果你对Windows Workflow Foundation(WF)一无所知,当看到扩展C#与元编程(一)中由MW编译器生成的FirstLook.mw.cs时,也许这么在想:我KAO,这是C#版的汇 ...
- 30分钟新手git教程
本文转载自:http://igeekbar.com/igeekbar/post/82.htm Git近些年的火爆程度非同一般,这个版本控制系统被广泛地用在大型开源项目(比如Linux),不同规模的团队 ...
- base和this
base//只能继承其直接基类成员 常用于对象初始化时和基类通信1.base局限于构造函数.实例方法.实例属性访问其中2.base调用直接基类已被重写的方法,或者所有父类的非重载方法3.base制定创 ...